sysprof-1.2.0/0000755000175000017500000000000012022706430010214 500000000000000sysprof-1.2.0/ChangeLog0000644000175000017500000000000012021176713011700 00000000000000sysprof-1.2.0/signal-handler.h0000644000175000017500000000214112021176713013177 00000000000000/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- */ /* Sysprof -- Sampling, systemwide CPU profiler * Copyright (C) 2005 Søren Sandmann (sandmann@daimi.au.dk) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef void (* SignalFunc) (int signo, gpointer data); gboolean signal_set_handler (int signo, SignalFunc handler, gpointer data, GError **err); void signal_unset_handler (int signo); sysprof-1.2.0/sysprof-icon-32.png0000644000175000017500000000440112021176713013522 00000000000000PNG  IHDR szzgAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxڤW{P=.~jӚ#DLhGʹLG#aZmMLlLѦP ku]ݞoY2 ݙ;{||s$@3?QdBz u´_9# .f6S}>ݻWN^ ?˒'4''֭[& $֑'Nt[ó|Wi擒ׯoUT2lQll+{߿?`4lAO m׮]۷oWglٲ;wv޽?Dg>nSjjjjБC 555*++7od:9yqqq Fd _ >.a#0֭[M,|Ν{aӦM?d(GFF܌F3>GDh@ brrz||nnDYUU>|+V`ǎBkJJJֈP??>6huPDW/&=N h ">% ҡ!'HBm۶Y333AJϐd]@X<>5:PK.;|Qg+ v"tbdZbOE{Sb޽ylx~'rK+3g#֠6l1p+ `6@51wnůpZjOZZ|= Yx8~xƗ^u~ +3Utװ&"h K%R >1.ë$/u2%Z5krOB1deemgoܸ?Wg_Ģˈ5H4qf2j-C- ybf+܂l|o [XIIIesΤH 0N9+_9&)Tj-6 =EgdD[e":(**Djj ZZZ&.Lsٌ@vGGnި@]\N x.'\EN`^',zL@V㑗'Qw>PL,G)9Ocd]2Ch7Ox<~)DێHD9r/ >O鎗Jƙ`jHEPI,P*szȂAچ YൣGOCңQ.Y"k\dV8駚3y+6Ta19R두}ނFB46RlR]IB)PjGah8nbR3xR.!#+KjApSh :kshgt3A<S:潀pX"*^- Qhȉ?U×`}!Sn̞@ XͬXD`on C]ͥFQ\ w?71!R!1MLmtG|(~'aY;|lnӮzXp ځNT^s1tA4%Us$nJ-xd4&mH=bcua!Pq2RgqP9J-jN^Z;{B~tQtH\p;_@龈 OZ ^Rn{큷<,OB9Aݾ}o{#bg\ 3mg\_:F v({~hb$wT̙3XtiZ-Fx RVVv29ڈ̌TƧBNZc^D\4_c`u\LGg._\Ez_ FyOF]9,眧L&G5:(2݋k!F6q2i~t\i@NԬ,s'ϰ*NA48b|.+YVnGhxQφby[`A U-4dzxh!v+&09JB&""; G'p8{rX/ IENDB`sysprof-1.2.0/signal-handler.c0000644000175000017500000001132212021176713013173 00000000000000/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- */ /* Sysprof -- Sampling, systemwide CPU profiler * Copyright (C) 2005 Søren Sandmann (sandmann@daimi.au.dk) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "watch.h" #include "signal-handler.h" typedef struct SignalWatch SignalWatch; struct SignalWatch { int signo; SignalFunc handler; gpointer user_data; struct sigaction old_action; SignalWatch * next; }; static int read_end = -1; static int write_end = -1; static SignalWatch *signal_watches = NULL; static SignalWatch * lookup_signal_watch (int signo) { SignalWatch *w; for (w = signal_watches; w != NULL; w = w->next) { if (w->signo == signo) return w; } return NULL; } static void remove_signal_watch (SignalWatch *watch) { SignalWatch *prev, *w; g_return_if_fail (watch != NULL); prev = NULL; for (w = signal_watches; w != NULL; w = w->next) { if (w == watch) { if (prev) prev->next = w->next; else signal_watches = w->next; break; } prev = w; } } static void signal_handler (int signo, siginfo_t *info, void *data) { /* FIXME: I suppose we should handle short * and non-successful writes ... * * And also, there is a deadlock if so many signals arrive that * write() blocks. Then we will be stuck right here, and the * main loop will never run. Kinda hard to fix without dropping * signals ... * */ write (write_end, &signo, sizeof (int)); } static void on_read (gpointer data) { SignalWatch *watch; int signo; /* FIXME: handle short read I suppose */ read (read_end, &signo, sizeof (int)); watch = lookup_signal_watch (signo); if (watch) watch->handler (signo, watch->user_data); } static gboolean create_pipe (int *read_end, int *write_end, GError **err) { int p[2]; if (pipe (p) < 0) { /* FIXME - create an error */ return FALSE; } /* FIXME: We should probably make the fd's non-blocking */ if (read_end) *read_end = p[0]; if (write_end) *write_end = p[1]; return TRUE; } static gboolean install_signal_handler (int signo, struct sigaction *old_action, GError **err) { struct sigaction action; memset (&action, 0, sizeof (action)); action.sa_sigaction = signal_handler; sigemptyset (&action.sa_mask); action.sa_flags = SA_SIGINFO; if (sigaction (signo, &action, old_action) < 0) { /* FIXME - create an error */ return TRUE; } return TRUE; } static void signal_watch_free (SignalWatch *watch) { remove_signal_watch (watch); g_free (watch); } gboolean signal_set_handler (int signo, SignalFunc handler, gpointer data, GError **err) { SignalWatch *watch; g_return_val_if_fail (lookup_signal_watch (signo) == NULL, FALSE); if (read_end == -1) { if (!create_pipe (&read_end, &write_end, err)) return FALSE; fd_add_watch (read_end, NULL); fd_set_read_callback (read_end, on_read); } watch = g_new0 (SignalWatch, 1); watch->signo = signo; watch->handler = handler; watch->user_data = data; watch->next = signal_watches; signal_watches = watch; if (!install_signal_handler (signo, &watch->old_action, err)) { signal_watch_free (watch); return FALSE; } return TRUE; } void signal_unset_handler (int signo) { SignalWatch *watch; watch = lookup_signal_watch (signo); g_return_if_fail (watch != NULL); sigaction (signo, &watch->old_action, NULL); signal_watch_free (watch); } sysprof-1.2.0/unwind.c0000644000175000017500000001575212021176713011622 00000000000000#include "elfparser.h" #include #include "util.h" /* Pointer encodings, from dwarf2.h. */ typedef enum { DW_EH_PE_absptr = 0x00, /* */ DW_EH_PE_omit = 0xff, /* Value is not there */ DW_EH_PE_uleb128 = 0x01, DW_EH_PE_udata2 = 0x02, DW_EH_PE_udata4 = 0x03, DW_EH_PE_udata8 = 0x04, DW_EH_PE_sleb128 = 0x09, DW_EH_PE_sdata2 = 0x0A, DW_EH_PE_sdata4 = 0x0B, DW_EH_PE_sdata8 = 0x0C, DW_EH_PE_signed = 0x08, DW_EH_PE_pcrel = 0x10, /* Value is *(cur + val) */ DW_EH_PE_textrel = 0x20, /* Value is *(&text + val) */ DW_EH_PE_datarel = 0x30, /* Value is *(&data + val) */ DW_EH_PE_funcrel = 0x40, /* Value is *(fde.pc_begin + val) */ DW_EH_PE_aligned = 0x50, /* Value is absolute, and stored * at next align */ DW_EH_PE_indirect = 0x80 } PointerEncoding; typedef struct EncodedPointer EncodedPointer; struct EncodedPointer { PointerEncoding encoding; guint64 value; }; static guint64 get_length (const guchar **data) { guint64 len; len = *(guint32 *)*data; *data += 4; if (len == 0xffffffff) { len = *(guint64 *)data; *data += 8; } return len; } static guint64 decode_uleb128 (const guchar **data) { guint64 result; int shift; guchar b; result = 0; shift = 0; do { b = *(*data)++; result |= (b & 0x7f) << shift; shift += 7; } while (b & 0x80); return result; } static gint64 decode_sleb128 (const guchar **data) { gint64 result; int shift; guchar b; result = 0; shift = 0; do { b = *(*data)++; result |= (b & 0x7f) << shift; shift += 7; } while (b & 0x80); if (b & 0x40 && shift < 64) result |= - (1 << shift); return result; } static void decode_block (const guchar **data) { int len; /* FIXME */ len = decode_uleb128 (data); (*data) += len; } static gulong decode_address (const guchar **data) { /* FIXME */ gulong r; r = *(guint32 *)*data; (*data) += 4; return r; } static const char * decode_instruction (const guchar **data) { int opcode = *(*data)++; int high2 = (opcode & 0xc0) >> 6; int low6 = (opcode & 0x3f); if (high2 == 0x01) { return "DW_CFA_advance_loc"; } else if (high2 == 0x02) { g_print ("register: %d\n", low6); g_print ("offset: "FMT64"\n", decode_uleb128 (data)); return "DW_CFA_offset"; } else if (high2 == 0x03) { return "DW_CFA_restore"; } else { g_assert ((opcode & 0xc0) == 0); switch (opcode) { case 0x0: return "DW_CFA_nop"; case 0x01: g_print ("addr: %p\n", (void *)decode_address (data)); return "DW_CFA_set_loc"; case 0x02: (*data)++; return "DW_CFA_advance_loc1"; case 0x03: (*data) += 2; return "DW_CFA_advance_loc2"; case 0x04: (*data) += 4; return "DW_CFA_advance_loc4"; case 0x05: decode_uleb128 (data); decode_uleb128 (data); return "DW_CFA_offset_extended"; case 0x06: decode_uleb128 (data); return "DW_CFA_restore_extended"; case 0x07: decode_uleb128 (data); return "DW_CFA_undefined"; case 0x08: decode_uleb128 (data); return "DW_CFA_same_value"; case 0x09: decode_uleb128 (data); decode_uleb128 (data); return "DW_CFA_register"; case 0x0a: return "DW_CFA_remember_state"; case 0x0b: return "DW_CFA_restore_state"; case 0x0c: g_print ("reg: "FMT64"\n", decode_uleb128 (data)); g_print ("off: "FMT64"\n", decode_uleb128 (data)); return "DW_CFA_def_cfa"; case 0x0d: decode_uleb128 (data); return "DW_CFA_def_cfa_register"; case 0x0e: decode_uleb128 (data); return "DW_CFA_def_cfa_offset"; case 0x0f: decode_block (data); return "DW_CFA_def_cfa_expression"; case 0x10: decode_uleb128 (data); decode_block (data); return "DW_CFA_expression"; case 0x11: decode_uleb128 (data); decode_sleb128 (data); return "DW_CFA_offset_extended_sf"; case 0x12: decode_uleb128 (data); decode_sleb128 (data); return "DW_CFA_def_cfa_sf"; case 0x13: decode_sleb128 (data); return "DW_CFA_def_cfa_offset_sf"; case 0x14: decode_uleb128 (data); decode_uleb128 (data); return "DW_CFA_val_offset"; case 0x15: decode_uleb128 (data); decode_sleb128 (data); return "DW_CFA_val_offset_sf"; case 0x16: decode_uleb128 (data); decode_block (data); return "DW_CFA_val_expression"; case 0x1c: return "DW_CFA_lo_user"; case 0x3f: return "DW_CFA_hi_user"; default: return "UNKNOWN INSTRUCTION"; } } } typedef struct CIE CIE; struct CIE { PointerEncoding encoding; }; static void decode_cie (const guchar **data, const guchar *end) { gboolean has_augmentation; guint64 aug_len; const char *augmentation; CIE *cie; int i, field; g_print ("version: %d\n", *(*data)++); augmentation = (*data); *data += strlen (*data) + 1; g_print ("code alignment: "FMT64"\n", decode_uleb128 (data)); g_print ("data alignment: %lld\n", decode_sleb128 (data)); g_print ("return register: "FMT64"\n", decode_uleb128 (data)); g_print ("augmentation: %s\n", augmentation); if (augmentation[0] == 'z') { aug_len = decode_uleb128 (data); g_print ("len: "FMT64"\n", aug_len); for (i = 1; augmentation[i] != 0; ++i) { if (augmentation[i] == 'L') { } } } if (has_augmentation) { g_print ("%x\n", **data); *data += aug_len; } while (*data < end) g_print (" %s\n", decode_instruction (data)); } static gboolean decode_fde (const guchar **data, const guchar *end) { return FALSE; } static gboolean decode_entry (const guchar **data, gboolean eh_frame) { guint64 len; const guchar *end; gboolean is_cie; guint64 id; len = get_length (data); if (len == 0) return FALSE; end = *data + len; g_print ("length: "FMT64"\n", len); /* CIE_id is 0 for eh frames, and 0xffffffff/0xffffffffffffffff for .debug_frame */ id = *(guint32 *)*data; g_print ("id: %lld\n", id); is_cie = (eh_frame && id == 0) || (!eh_frame && id == 0xffffffff); if (is_cie) g_print ("is cie\n"); else g_print ("is not cie\n"); *data += 4; if (is_cie) decode_cie (data, end); else decode_fde (data, end); return TRUE; } /* The correct API is probably something like * * gboolean * unwind (ElfParser *parser, * gulong *regs * int n_regs, * MemoryReader reader, * gpointer data); * */ void unwind (ElfParser *elf) { const guchar *data; gboolean eh_f; if ((data = elf_parser_get_debug_frame (elf))) { g_print ("Using .debug_frame\n"); eh_f = FALSE; } else if ((data = elf_parser_get_eh_frame (elf))) { g_print ("Using .eh_frame\n"); eh_f = TRUE; } else { g_print ("no debug info found\n"); return; } while (decode_entry (&data, eh_f)) return ; ; } sysprof-1.2.0/tracker.c0000644000175000017500000005457412021210325011742 00000000000000#include #include #include #include #include #include #include "tracker.h" #include "stackstash.h" #include "binfile.h" #include "elfparser.h" typedef struct new_process_t new_process_t; typedef struct new_map_t new_map_t; typedef struct sample_t sample_t; typedef struct fork_t fork_t; typedef struct exit_t exit_t; struct tracker_t { StackStash *stash; size_t n_event_bytes; size_t n_allocated_bytes; uint8_t * events; }; typedef enum { NEW_PROCESS, NEW_MAP, SAMPLE, FORK, EXIT } event_type_t; struct new_process_t { uint32_t header; char command_line[256]; }; struct fork_t { uint32_t header; int32_t child_pid; }; struct exit_t { uint32_t header; }; struct new_map_t { uint32_t header; char filename[PATH_MAX]; uint64_t start; uint64_t end; uint64_t offset; uint64_t inode; }; struct sample_t { uint32_t header; StackNode * trace; }; #define TYPE_SHIFT 29 #define PID_MASK ((uint32_t)((1 << TYPE_SHIFT) - 1)) #define MAKE_HEADER(type, pid) \ ((uint32_t)((((uint32_t)pid) & PID_MASK) | (type << TYPE_SHIFT))) #define GET_PID(header) \ (header & PID_MASK) #define GET_TYPE(header) \ (header >> TYPE_SHIFT) #define DEFAULT_SIZE (1024 * 1024 * 4) static char ** get_lines (const char *format, pid_t pid) { char *filename = g_strdup_printf (format, pid); char **result = NULL; char *contents; if (g_file_get_contents (filename, &contents, NULL, NULL)) { result = g_strsplit (contents, "\n", -1); g_free (contents); } g_free (filename); return result; } static void fake_new_process (tracker_t *tracker, pid_t pid) { char **lines; gboolean done = FALSE; if ((lines = get_lines ("/proc/%d/cmdline", pid))) { if (lines[0] && strlen (lines[0]) > 0) { tracker_add_process (tracker, pid, lines[0]); done = TRUE; } g_strfreev (lines); } if (!done && (lines = get_lines ("/proc/%d/status", pid))) { int i; for (i = 0; lines[i] != NULL; ++i) { if (strncmp ("Name:", lines[i], 5) == 0) { char *name = g_strstrip (strchr (lines[i], ':') + 1); if (strlen (name) > 0) { tracker_add_process (tracker, pid, name); done = TRUE; break; } } } g_strfreev (lines); } if (!done) g_print ("failed to fake %d\n", pid); } static void fake_new_map (tracker_t *tracker, pid_t pid) { char **lines; if ((lines = get_lines ("/proc/%d/maps", pid))) { int i; for (i = 0; lines[i] != NULL; ++i) { char file[256]; gulong start; gulong end; gulong offset; gulong inode; int count; file[255] = '\0'; count = sscanf ( lines[i], "%lx-%lx %*15s %lx %*x:%*x %lu %255s", &start, &end, &offset, &inode, file); if (count == 5) { if (strcmp (file, "[vdso]") == 0) { /* For the vdso, the kernel reports 'offset' as the * the same as the mapping addres. This doesn't make * any sense to me, so we just zero it here. There * is code in binfile.c (read_inode) that returns 0 * for [vdso]. */ offset = 0; inode = 0; } tracker_add_map (tracker, pid, start, end, offset, inode, file); } } g_strfreev (lines); } } static void populate_from_proc (tracker_t *tracker) { GDir *proc = g_dir_open ("/proc", 0, NULL); const char *name; if (!proc) return; while ((name = g_dir_read_name (proc))) { pid_t pid; char *end; pid = strtol (name, &end, 10); if (*end == 0) { fake_new_process (tracker, pid); fake_new_map (tracker, pid); } } g_dir_close (proc); } static double timeval_to_ms (const GTimeVal *timeval) { return (timeval->tv_sec * G_USEC_PER_SEC + timeval->tv_usec) / 1000.0; } static double time_diff (const GTimeVal *first, const GTimeVal *second) { double first_ms = timeval_to_ms (first); double second_ms = timeval_to_ms (second); return first_ms - second_ms; } tracker_t * tracker_new (void) { tracker_t *tracker = g_new0 (tracker_t, 1); GTimeVal before, after; tracker->n_event_bytes = 0; tracker->n_allocated_bytes = DEFAULT_SIZE; tracker->events = g_malloc (DEFAULT_SIZE); tracker->stash = stack_stash_new (NULL); g_get_current_time (&before); populate_from_proc (tracker); g_get_current_time (&after); #if 0 g_print ("Time to populate %f\n", time_diff (&after, &before)); #endif return tracker; } void tracker_free (tracker_t *tracker) { stack_stash_unref (tracker->stash); g_free (tracker->events); g_free (tracker); } #define COPY_STRING(dest, src) \ do \ { \ strncpy (dest, src, sizeof (dest) - 1); \ dest[sizeof (dest) - 1] = 0; \ } \ while (0) static void tracker_append (tracker_t *tracker, void *event, int n_bytes) { if (tracker->n_allocated_bytes - tracker->n_event_bytes < n_bytes) { size_t new_size = tracker->n_allocated_bytes * 2; tracker->events = g_realloc (tracker->events, new_size); tracker->n_allocated_bytes = new_size; } g_assert (tracker->n_allocated_bytes - tracker->n_event_bytes >= n_bytes); memcpy (tracker->events + tracker->n_event_bytes, event, n_bytes); #if 0 g_print (" (address %p)\n", tracker->events + tracker->n_event_bytes); #endif tracker->n_event_bytes += n_bytes; } void tracker_add_process (tracker_t * tracker, pid_t pid, const char *command_line) { new_process_t event; #if 0 g_print ("Add new process %s %d to tracker ", command_line, pid); #endif event.header = MAKE_HEADER (NEW_PROCESS, pid); COPY_STRING (event.command_line, command_line); tracker_append (tracker, &event, sizeof (event)); } void tracker_add_fork (tracker_t *tracker, pid_t pid, pid_t child_pid) { fork_t event; event.header = MAKE_HEADER(FORK, pid); event.child_pid = child_pid; tracker_append (tracker, &event, sizeof (event)); } void tracker_add_exit (tracker_t *tracker, pid_t pid) { exit_t event; event.header = MAKE_HEADER (EXIT, pid); tracker_append (tracker, &event, sizeof (event)); } void tracker_add_map (tracker_t * tracker, pid_t pid, uint64_t start, uint64_t end, uint64_t offset, uint64_t inode, const char *filename) { new_map_t event; event.header = MAKE_HEADER (NEW_MAP, pid); COPY_STRING (event.filename, filename); event.start = start; event.end = end; event.offset = offset; event.inode = inode; tracker_append (tracker, &event, sizeof (event)); } void tracker_add_sample (tracker_t *tracker, pid_t pid, uint64_t *ips, int n_ips) { sample_t event; event.header = MAKE_HEADER (SAMPLE, pid); event.trace = stack_stash_add_trace (tracker->stash, ips, n_ips, 1); tracker_append (tracker, &event, sizeof (event)); } /* */ typedef struct state_t state_t; typedef struct process_t process_t; typedef struct map_t map_t; struct process_t { pid_t pid; char * comm; GArray * maps; }; struct map_t { char * filename; uint64_t start; uint64_t end; uint64_t offset; uint64_t inode; }; struct state_t { GHashTable *processes_by_pid; GHashTable *unique_comms; GHashTable *unique_symbols; GHashTable *bin_files; }; static const map_t * process_locate_map (process_t *process, gulong addr) { GArray *maps = process->maps; int i; for (i = 0; i < process->maps->len; ++i) { map_t *map = &g_array_index (maps, map_t, i); if (addr >= map->start && addr < map->end) { if (i > 0) { map_t tmp = *map; memmove (&(g_array_index (maps, map_t, 1)), &(g_array_index (maps, map_t, 0)), i * sizeof (map_t)); g_array_index (maps, map_t, 0) = tmp; } return &g_array_index (maps, map_t, 0); } } return NULL; } static void create_map (state_t *state, new_map_t *new_map) { process_t *process; map_t map; int i; pid_t pid = GET_PID (new_map->header); process = g_hash_table_lookup ( state->processes_by_pid, GINT_TO_POINTER (pid)); if (!process) return; map.filename = g_strdup (new_map->filename); map.start = new_map->start; map.end = new_map->end; map.offset = new_map->offset; map.inode = new_map->inode; /* Remove existing maps that overlap the new one */ for (i = 0; i < process->maps->len; ++i) { map_t *m = &g_array_index (process->maps, map_t, i); if (m->start < map.end && m->end > map.start) { g_free (m->filename); g_array_remove_index (process->maps, i); } } g_array_append_vals (process->maps, &map, 1); } static void destroy_process (process_t *process) { int i; g_free (process->comm); for (i = 0; i < process->maps->len; ++i) { map_t *map = &g_array_index (process->maps, map_t, i); g_free (map->filename); } g_array_free (process->maps, TRUE); g_free (process); } static void create_process (state_t *state, new_process_t *new_process) { pid_t pid = GET_PID (new_process->header); const char *comm = new_process->command_line; process_t *process = g_hash_table_lookup (state->processes_by_pid, GINT_TO_POINTER (pid)); if (process) { g_free (process->comm); process->comm = g_strdup (comm); } else { process = g_new0 (process_t, 1); process->pid = pid; process->comm = g_strdup (comm); process->maps = g_array_new (FALSE, FALSE, sizeof (map_t)); g_hash_table_insert ( state->processes_by_pid, GINT_TO_POINTER (process->pid), process); } } static void process_fork (state_t *state, fork_t *fork) { pid_t ppid = GET_PID (fork->header); process_t *parent = g_hash_table_lookup ( state->processes_by_pid, GINT_TO_POINTER (ppid)); process_t *child; if (ppid == fork->child_pid) { /* Just a new thread being spawned */ return; } child = g_new0 (process_t, 1); if (parent) child->comm = g_strdup (parent->comm); else child->comm = g_strdup_printf ("[pid %d]", fork->child_pid); child->pid = fork->child_pid; child->maps = g_array_new (FALSE, FALSE, sizeof (map_t)); if (parent) { int i; for (i = 0; i < parent->maps->len; ++i) { map_t copy = g_array_index (parent->maps, map_t, i); copy.filename = g_strdup (copy.filename); g_array_append_val (child->maps, copy); } } g_hash_table_insert ( state->processes_by_pid, GINT_TO_POINTER (child->pid), child); } static void process_exit (state_t *state, exit_t *exit) { #if 0 g_print ("Exit for %d\n", exit->pid); #endif /* ignore for now */ } static void free_process (gpointer data) { process_t *process = data; destroy_process (process); } static state_t * state_new (void) { state_t *state = g_new0 (state_t, 1); state->processes_by_pid = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, free_process); state->unique_symbols = g_hash_table_new (g_direct_hash, g_direct_equal); state->unique_comms = g_hash_table_new (g_str_hash, g_str_equal); state->bin_files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)bin_file_free); return state; } static void state_free (state_t *state) { g_hash_table_destroy (state->processes_by_pid); g_hash_table_destroy (state->unique_symbols); g_hash_table_destroy (state->unique_comms); g_hash_table_destroy (state->bin_files); g_free (state); } typedef struct { gulong address; char *name; } kernel_symbol_t; static void parse_kallsym_line (const char *line, GArray *table) { char **tokens = g_strsplit_set (line, " \t", -1); if (tokens[0] && tokens[1] && tokens[2]) { glong address; char *endptr; address = strtoul (tokens[0], &endptr, 16); if (*endptr == '\0' && (strcmp (tokens[1], "T") == 0 || strcmp (tokens[1], "t") == 0)) { kernel_symbol_t sym; sym.address = address; sym.name = g_strdup (tokens[2]); g_array_append_val (table, sym); } } g_strfreev (tokens); } static gboolean parse_kallsyms (const char *kallsyms, GArray *table) { const char *sol; const char *eol; sol = kallsyms; eol = strchr (sol, '\n'); while (eol) { char *line = g_strndup (sol, eol - sol); parse_kallsym_line (line, table); g_free (line); sol = eol + 1; eol = strchr (sol, '\n'); } if (table->len <= 1) return FALSE; return TRUE; } static int compare_syms (gconstpointer a, gconstpointer b) { const kernel_symbol_t *sym_a = a; const kernel_symbol_t *sym_b = b; if (sym_a->address > sym_b->address) return 1; else if (sym_a->address == sym_b->address) return 0; else return -1; } static kernel_symbol_t * do_lookup (kernel_symbol_t *symbols, gulong address, int first, int last) { if (address >= symbols[last].address) { return &(symbols[last]); } else if (last - first < 3) { while (last >= first) { if (address >= symbols[last].address) return &(symbols[last]); last--; } return NULL; } else { int mid = (first + last) / 2; if (symbols[mid].address > address) return do_lookup (symbols, address, first, mid); else return do_lookup (symbols, address, mid, last); } } static GArray * get_kernel_symbols (void) { static GArray *kernel_syms; static gboolean initialized = FALSE; #if 0 find_kernel_binary(); #endif if (!initialized) { char *kallsyms; if (g_file_get_contents ("/proc/kallsyms", &kallsyms, NULL, NULL)) { if (kallsyms) { kernel_syms = g_array_new (TRUE, TRUE, sizeof (kernel_symbol_t)); if (parse_kallsyms (kallsyms, kernel_syms)) { g_array_sort (kernel_syms, compare_syms); } else { g_array_free (kernel_syms, TRUE); kernel_syms = NULL; } } g_free (kallsyms); } if (!kernel_syms) { g_print ("Warning: /proc/kallsyms could not be " "read. Kernel symbols will not be available\n"); } initialized = TRUE; } return kernel_syms; } static const char skip_kernel_symbols[][32] = { /* IRQ stack */ "common_interrupt", "apic_timer_interrupt", "smp_apic_timer_interrupt", "hrtimer_interrupt", "__run_hrtimer", "perf_swevent_hrtimer", "perf_event_overflow", "__perf_event_overflow", "perf_prepare_sample", "perf_callchain", "perf_swcounter_hrtimer", "perf_counter_overflow", "__perf_counter_overflow", "perf_counter_output", /* NMI stack */ "nmi_stack_correct", "do_nmi", "notify_die", "atomic_notifier_call_chain", "notifier_call_chain", "perf_event_nmi_handler", "perf_counter_nmi_handler", "intel_pmu_handle_irq", "perf_event_overflow", "perf_counter_overflow", "__perf_event_overflow", "perf_prepare_sample", "perf_callchain", "" }; const char * lookup_kernel_symbol (gulong address) { kernel_symbol_t *result; GArray *ksyms = get_kernel_symbols (); const char *sym; int i; if (ksyms->len == 0) return NULL; result = do_lookup ((kernel_symbol_t *)ksyms->data, address, 0, ksyms->len - 1); sym = result? result->name : NULL; /* This is a workaround for a kernel bug, where it reports not * only the kernel stack, but also the IRQ stack for the * timer interrupt that generated the stack. * * The stack as reported by the kernel looks like this: * * [ip] [irq stack] [real kernel stack] * * Below we filter out the [irq stack] */ i = 0; while (sym && skip_kernel_symbols[i][0] != '\0') { if (strcmp (sym, skip_kernel_symbols[i]) == 0) { sym = NULL; break; } i++; } return sym; } /* Note that 'unique_symbols' is a direct_hash table. Ie., we * rely on the address of symbol strings being different for different * symbols. */ static char * unique_dup (GHashTable *unique_symbols, const char *sym) { char *result; result = g_hash_table_lookup (unique_symbols, sym); if (!result) { result = elf_demangle (sym); g_hash_table_insert (unique_symbols, (char *)sym, result); } return result; } static const char * make_message (state_t *state, const char *format, ...) { va_list args; char *message; char *result; va_start (args, format); g_vasprintf (&message, format, args); va_end (args); result = g_hash_table_lookup (state->unique_comms, message); if (result) { g_free (message); } else { result = message; g_hash_table_insert (state->unique_comms, result, result); } return result; } static bin_file_t * state_get_bin_file (state_t *state, const char *filename) { bin_file_t *bf = g_hash_table_lookup (state->bin_files, filename); if (!bf) { bf = bin_file_new (filename); g_hash_table_insert (state->bin_files, g_strdup (filename), bf); } return bf; } static char * lookup_symbol (state_t *state, process_t *process, uint64_t address, gboolean kernel) { const char *sym; g_assert (process); if (kernel) { sym = lookup_kernel_symbol (address); } else { const map_t *map = process_locate_map (process, address); if (!map) { sym = make_message (state, "No map [%s]", process->comm); } else { bin_file_t *bin_file = state_get_bin_file (state, map->filename); const bin_symbol_t *bin_sym; address -= map->start; address += map->offset; if (map->inode && !bin_file_check_inode (bin_file, map->inode)) { /* If the inodes don't match, it's probably because the * file has changed since the process was started. */ sym = make_message (state, "%s: inode mismatch", map->filename); } else { bin_sym = bin_file_lookup_symbol (bin_file, address); sym = bin_symbol_get_name (bin_file, bin_sym); } } } if (sym) return unique_dup (state->unique_symbols, sym); else return NULL; } typedef struct context_info_t context_info_t; struct context_info_t { enum perf_callchain_context context; char name[32]; }; static const context_info_t context_info[] = { { PERF_CONTEXT_HV, "- - hypervisor - -" }, { PERF_CONTEXT_KERNEL, "- - kernel - -" }, { PERF_CONTEXT_USER, "- - user - - " }, { PERF_CONTEXT_GUEST, "- - guest - - " }, { PERF_CONTEXT_GUEST_KERNEL, "- - guest kernel - -" }, { PERF_CONTEXT_GUEST_USER, "- - guest user - -" }, }; static const char *const everything = "[Everything]"; static const context_info_t * get_context_info (enum perf_callchain_context context) { int i; for (i = 0; i < sizeof (context_info) / sizeof (context_info[0]); ++i) { const context_info_t *info = &context_info[i]; if (info->context == context) return info; } return NULL; } static void process_sample (state_t *state, StackStash *resolved, sample_t *sample) { const context_info_t *context = NULL; const char *cmdline; uint64_t stack_addrs[256]; uint64_t *resolved_traces; process_t *process; StackNode *n; int len; pid_t pid = GET_PID (sample->header); process = g_hash_table_lookup ( state->processes_by_pid, GINT_TO_POINTER (pid)); if (!process) { static gboolean warned; if (!warned || pid != 0) { #if 0 g_print ("sample for unknown process %d\n", sample->pid); #endif warned = TRUE; } return; } len = 5; for (n = sample->trace; n != NULL; n = n->parent) len++; if (len > 256) resolved_traces = g_new (uint64_t, len); else resolved_traces = stack_addrs; len = 0; for (n = sample->trace; n != NULL; n = n->parent) { uint64_t address = n->data; const context_info_t *new_context; const char *symbol; new_context = get_context_info (address); if (new_context) { if (context) symbol = unique_dup (state->unique_symbols, context->name); else symbol = NULL; context = new_context; } else { gboolean kernel = context && context->context == PERF_CONTEXT_KERNEL; symbol = lookup_symbol (state, process, address, kernel); } if (symbol) resolved_traces[len++] = POINTER_TO_U64 (symbol); } if (context && context->context != PERF_CONTEXT_USER) { /* Kernel threads do not have a user part, so we end up here * without ever getting a user context. If this happens, * add the '- - kernel - - ' name, so that kernel threads * are properly blamed on the kernel */ resolved_traces[len++] = POINTER_TO_U64 (unique_dup (state->unique_symbols, context->name)); } cmdline = make_message (state, "[%s]", process->comm); resolved_traces[len++] = POINTER_TO_U64 (cmdline); resolved_traces[len++] = POINTER_TO_U64 ( unique_dup (state->unique_symbols, everything)); stack_stash_add_trace (resolved, resolved_traces, len, 1); if (resolved_traces != stack_addrs) g_free (resolved_traces); } Profile * tracker_create_profile (tracker_t *tracker) { uint8_t *end = tracker->events + tracker->n_event_bytes; StackStash *resolved_stash; Profile *profile; state_t *state; uint8_t *event; state = state_new (); resolved_stash = stack_stash_new (g_free); event = tracker->events; while (event < end) { event_type_t type = GET_TYPE (*(uint32_t *)event); switch (type) { case NEW_PROCESS: create_process (state, (new_process_t *)event); event += sizeof (new_process_t); break; case NEW_MAP: create_map (state, (new_map_t *)event); event += sizeof (new_map_t); break; case FORK: process_fork (state, (fork_t *)event); event += sizeof (fork_t); break; case EXIT: process_exit (state, (exit_t *)event); event += sizeof (exit_t); break; case SAMPLE: process_sample (state, resolved_stash, (sample_t *)event); event += sizeof (sample_t); break; } } profile = profile_new (resolved_stash); state_free (state); stack_stash_unref (resolved_stash); return profile; } sysprof-1.2.0/footreestore.c0000644000175000017500000026162512021176713013040 00000000000000/* gtktreestore.c * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "config.h" #include #include #include #include "footreedatalist.h" #include "footreestore.h" #define G_NODE(node) ((GNode *)node) #define FOO_TREE_STORE_IS_SORTED(tree) (((FooTreeStore*)(tree))->sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID) #define VALID_ITER(iter, tree_store) ((iter)!= NULL && (iter)->user_data != NULL && ((FooTreeStore*)(tree_store))->stamp == (iter)->stamp) /* Get rid of some macros that cause lots of g_atomic_get_pointer() */ #undef g_return_if_fail #undef GTK_TREE_MODEL #undef FOO_TREE_STORE #define g_return_if_fail(x) #define GTK_TREE_MODEL(m) ((GtkTreeModel *)m) #define FOO_TREE_STORE(m) ((FooTreeStore *)m) static void foo_tree_store_tree_model_init (GtkTreeModelIface *iface); static void foo_tree_store_drag_source_init(GtkTreeDragSourceIface *iface); static void foo_tree_store_drag_dest_init (GtkTreeDragDestIface *iface); static void foo_tree_store_sortable_init (GtkTreeSortableIface *iface); static void foo_tree_store_buildable_init (GtkBuildableIface *iface); static void foo_tree_store_finalize (GObject *object); static GtkTreeModelFlags foo_tree_store_get_flags (GtkTreeModel *tree_model); static gint foo_tree_store_get_n_columns (GtkTreeModel *tree_model); static GType foo_tree_store_get_column_type (GtkTreeModel *tree_model, gint index); static gboolean foo_tree_store_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path); static GtkTreePath *foo_tree_store_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter); static void foo_tree_store_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value); static gboolean foo_tree_store_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter); static gboolean foo_tree_store_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent); static gboolean foo_tree_store_iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter); static gint foo_tree_store_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter); static gboolean foo_tree_store_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n); static gboolean foo_tree_store_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child); static void foo_tree_store_set_n_columns (FooTreeStore *tree_store, gint n_columns); static void foo_tree_store_set_column_type (FooTreeStore *tree_store, gint column, GType type); static void foo_tree_store_increment_stamp (FooTreeStore *tree_store); /* DND interfaces */ static gboolean real_foo_tree_store_row_draggable (GtkTreeDragSource *drag_source, GtkTreePath *path); static gboolean foo_tree_store_drag_data_delete (GtkTreeDragSource *drag_source, GtkTreePath *path); static gboolean foo_tree_store_drag_data_get (GtkTreeDragSource *drag_source, GtkTreePath *path, GtkSelectionData *selection_data); static gboolean foo_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data); static gboolean foo_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, GtkSelectionData *selection_data); /* Sortable Interfaces */ static void foo_tree_store_sort (FooTreeStore *tree_store); static void foo_tree_store_sort_iter_changed (FooTreeStore *tree_store, GtkTreeIter *iter, gint column, gboolean emit_signal); static gboolean foo_tree_store_get_sort_column_id (GtkTreeSortable *sortable, gint *sort_column_id, GtkSortType *order); static void foo_tree_store_set_sort_column_id (GtkTreeSortable *sortable, gint sort_column_id, GtkSortType order); static void foo_tree_store_set_sort_func (GtkTreeSortable *sortable, gint sort_column_id, GtkTreeIterCompareFunc func, gpointer data, GDestroyNotify destroy); static void foo_tree_store_set_default_sort_func (GtkTreeSortable *sortable, GtkTreeIterCompareFunc func, gpointer data, GDestroyNotify destroy); static gboolean foo_tree_store_has_default_sort_func (GtkTreeSortable *sortable); /* buildable */ static gboolean foo_tree_store_buildable_custom_tag_start (GtkBuildable *buildable, GtkBuilder *builder, GObject *child, const gchar *tagname, GMarkupParser *parser, gpointer *data); static void foo_tree_store_buildable_custom_finished (GtkBuildable *buildable, GtkBuilder *builder, GObject *child, const gchar *tagname, gpointer user_data); static void validate_gnode (GNode *node); static void foo_tree_store_move (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *position, gboolean before); static inline void validate_tree (FooTreeStore *tree_store) { if (gtk_debug_flags & GTK_DEBUG_TREE) { g_assert (G_NODE (tree_store->root)->parent == NULL); validate_gnode (G_NODE (tree_store->root)); } } G_DEFINE_TYPE_WITH_CODE (FooTreeStore, foo_tree_store, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, foo_tree_store_tree_model_init) G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE, foo_tree_store_drag_source_init) G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST, foo_tree_store_drag_dest_init) G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE, foo_tree_store_sortable_init) G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, foo_tree_store_buildable_init)) static void foo_tree_store_class_init (FooTreeStoreClass *class) { GObjectClass *object_class; object_class = (GObjectClass *) class; object_class->finalize = foo_tree_store_finalize; } static void foo_tree_store_tree_model_init (GtkTreeModelIface *iface) { iface->get_flags = foo_tree_store_get_flags; iface->get_n_columns = foo_tree_store_get_n_columns; iface->get_column_type = foo_tree_store_get_column_type; iface->get_iter = foo_tree_store_get_iter; iface->get_path = foo_tree_store_get_path; iface->get_value = foo_tree_store_get_value; iface->iter_next = foo_tree_store_iter_next; iface->iter_children = foo_tree_store_iter_children; iface->iter_has_child = foo_tree_store_iter_has_child; iface->iter_n_children = foo_tree_store_iter_n_children; iface->iter_nth_child = foo_tree_store_iter_nth_child; iface->iter_parent = foo_tree_store_iter_parent; } static void foo_tree_store_drag_source_init (GtkTreeDragSourceIface *iface) { iface->row_draggable = real_foo_tree_store_row_draggable; iface->drag_data_delete = foo_tree_store_drag_data_delete; iface->drag_data_get = foo_tree_store_drag_data_get; } static void foo_tree_store_drag_dest_init (GtkTreeDragDestIface *iface) { iface->drag_data_received = foo_tree_store_drag_data_received; iface->row_drop_possible = foo_tree_store_row_drop_possible; } static void foo_tree_store_sortable_init (GtkTreeSortableIface *iface) { iface->get_sort_column_id = foo_tree_store_get_sort_column_id; iface->set_sort_column_id = foo_tree_store_set_sort_column_id; iface->set_sort_func = foo_tree_store_set_sort_func; iface->set_default_sort_func = foo_tree_store_set_default_sort_func; iface->has_default_sort_func = foo_tree_store_has_default_sort_func; } void foo_tree_store_buildable_init (GtkBuildableIface *iface) { iface->custom_tag_start = foo_tree_store_buildable_custom_tag_start; iface->custom_finished = foo_tree_store_buildable_custom_finished; } static void foo_tree_store_init (FooTreeStore *tree_store) { tree_store->root = g_node_new (NULL); /* While the odds are against us getting 0... */ do { tree_store->stamp = g_random_int (); } while (tree_store->stamp == 0); tree_store->sort_list = NULL; tree_store->sort_column_id = GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID; tree_store->columns_dirty = FALSE; tree_store->row_changed_id = g_signal_lookup ("row_changed", GTK_TYPE_TREE_MODEL); tree_store->row_inserted_id = g_signal_lookup ("row_inserted", GTK_TYPE_TREE_MODEL); tree_store->row_has_child_toggled_id = g_signal_lookup ("row_has_child_toggled", GTK_TYPE_TREE_MODEL); tree_store->rows_reordered_id = g_signal_lookup ("rows_reordered", GTK_TYPE_TREE_MODEL); } /** * foo_tree_store_new: * @n_columns: number of columns in the tree store * @Varargs: all #GType types for the columns, from first to last * * Creates a new tree store as with @n_columns columns each of the types passed * in. Note that only types derived from standard GObject fundamental types * are supported. * * As an example, foo_tree_store_new (3, G_TYPE_INT, G_TYPE_STRING, * GDK_TYPE_PIXBUF); will create a new #FooTreeStore with three columns, of type * int, string and #GdkPixbuf respectively. * * Return value: a new #FooTreeStore **/ FooTreeStore * foo_tree_store_new (gint n_columns, ...) { FooTreeStore *retval; va_list args; gint i; g_return_val_if_fail (n_columns > 0, NULL); retval = g_object_new (FOO_TYPE_TREE_STORE, NULL); foo_tree_store_set_n_columns (retval, n_columns); va_start (args, n_columns); for (i = 0; i < n_columns; i++) { GType type = va_arg (args, GType); if (! _foo_tree_data_list_check_type (type)) { g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type)); g_object_unref (retval); va_end (args); return NULL; } foo_tree_store_set_column_type (retval, i, type); } va_end (args); return retval; } /** * foo_tree_store_newv: * @n_columns: number of columns in the tree store * @types: an array of #GType types for the columns, from first to last * * Non vararg creation function. Used primarily by language bindings. * * Return value: a new #FooTreeStore **/ FooTreeStore * foo_tree_store_newv (gint n_columns, GType *types) { FooTreeStore *retval; gint i; g_return_val_if_fail (n_columns > 0, NULL); retval = g_object_new (FOO_TYPE_TREE_STORE, NULL); foo_tree_store_set_n_columns (retval, n_columns); for (i = 0; i < n_columns; i++) { if (! _foo_tree_data_list_check_type (types[i])) { g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i])); g_object_unref (retval); return NULL; } foo_tree_store_set_column_type (retval, i, types[i]); } return retval; } /** * foo_tree_store_set_column_types: * @tree_store: A #FooTreeStore * @n_columns: Number of columns for the tree store * @types: An array of #GType types, one for each column * * This function is meant primarily for #GObjects that inherit from * #FooTreeStore, and should only be used when constructing a new * #FooTreeStore. It will not function after a row has been added, * or a method on the #GtkTreeModel interface is called. **/ void foo_tree_store_set_column_types (FooTreeStore *tree_store, gint n_columns, GType *types) { gint i; g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); g_return_if_fail (tree_store->columns_dirty == 0); foo_tree_store_set_n_columns (tree_store, n_columns); for (i = 0; i < n_columns; i++) { if (! _foo_tree_data_list_check_type (types[i])) { g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i])); continue; } foo_tree_store_set_column_type (tree_store, i, types[i]); } } static void foo_tree_store_set_n_columns (FooTreeStore *tree_store, gint n_columns) { GType *new_columns; if (tree_store->n_columns == n_columns) return; new_columns = g_new0 (GType, n_columns); if (tree_store->column_headers) { /* copy the old header orders over */ if (n_columns >= tree_store->n_columns) memcpy (new_columns, tree_store->column_headers, tree_store->n_columns * sizeof (gchar *)); else memcpy (new_columns, tree_store->column_headers, n_columns * sizeof (GType)); g_free (tree_store->column_headers); } if (tree_store->sort_list) _foo_tree_data_list_header_free (tree_store->sort_list); tree_store->sort_list = _foo_tree_data_list_header_new (n_columns, tree_store->column_headers); tree_store->column_headers = new_columns; tree_store->n_columns = n_columns; } /** * foo_tree_store_set_column_type: * @tree_store: a #FooTreeStore * @column: column number * @type: type of the data to be stored in @column * * Supported types include: %G_TYPE_UINT, %G_TYPE_INT, %G_TYPE_UCHAR, * %G_TYPE_CHAR, %G_TYPE_BOOLEAN, %G_TYPE_POINTER, %G_TYPE_FLOAT, * %G_TYPE_DOUBLE, %G_TYPE_STRING, %G_TYPE_OBJECT, and %G_TYPE_BOXED, along with * subclasses of those types such as %GDK_TYPE_PIXBUF. * **/ static void foo_tree_store_set_column_type (FooTreeStore *tree_store, gint column, GType type) { if (!_foo_tree_data_list_check_type (type)) { g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type)); return; } tree_store->column_headers[column] = type; } static gboolean node_free (GNode *node, gpointer data) { if (node->data) _foo_tree_data_list_free (node->data, (GType*)data); node->data = NULL; return FALSE; } static void foo_tree_store_finalize (GObject *object) { FooTreeStore *tree_store = FOO_TREE_STORE (object); g_node_traverse (tree_store->root, G_POST_ORDER, G_TRAVERSE_ALL, -1, node_free, tree_store->column_headers); g_node_destroy (tree_store->root); _foo_tree_data_list_header_free (tree_store->sort_list); g_free (tree_store->column_headers); if (tree_store->default_sort_destroy) { GDestroyNotify d = tree_store->default_sort_destroy; tree_store->default_sort_destroy = NULL; d (tree_store->default_sort_data); tree_store->default_sort_data = NULL; } /* must chain up */ G_OBJECT_CLASS (foo_tree_store_parent_class)->finalize (object); } /* fulfill the GtkTreeModel requirements */ /* NOTE: FooTreeStore::root is a GNode, that acts as the parent node. However, * it is not visible to the tree or to the user., and the path "0" refers to the * first child of FooTreeStore::root. */ static GtkTreeModelFlags foo_tree_store_get_flags (GtkTreeModel *tree_model) { return GTK_TREE_MODEL_ITERS_PERSIST; } static gint foo_tree_store_get_n_columns (GtkTreeModel *tree_model) { FooTreeStore *tree_store = (FooTreeStore *) tree_model; tree_store->columns_dirty = TRUE; return tree_store->n_columns; } static GType foo_tree_store_get_column_type (GtkTreeModel *tree_model, gint index) { FooTreeStore *tree_store = (FooTreeStore *) tree_model; g_return_val_if_fail (index < tree_store->n_columns, G_TYPE_INVALID); tree_store->columns_dirty = TRUE; return tree_store->column_headers[index]; } static gboolean foo_tree_store_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path) { FooTreeStore *tree_store = (FooTreeStore *) tree_model; GtkTreeIter parent; gint *indices; gint depth, i; tree_store->columns_dirty = TRUE; indices = gtk_tree_path_get_indices (path); depth = gtk_tree_path_get_depth (path); g_return_val_if_fail (depth > 0, FALSE); parent.stamp = tree_store->stamp; parent.user_data = tree_store->root; if (!foo_tree_store_iter_nth_child (tree_model, iter, &parent, indices[0])) return FALSE; for (i = 1; i < depth; i++) { parent = *iter; if (!foo_tree_store_iter_nth_child (tree_model, iter, &parent, indices[i])) return FALSE; } return TRUE; } static GtkTreePath * foo_tree_store_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter) { FooTreeStore *tree_store = (FooTreeStore *) tree_model; GtkTreePath *retval; GNode *tmp_node; gint i = 0; g_return_val_if_fail (iter->user_data != NULL, NULL); g_return_val_if_fail (iter->stamp == tree_store->stamp, NULL); validate_tree (tree_store); if (G_NODE (iter->user_data)->parent == NULL && G_NODE (iter->user_data) == tree_store->root) return gtk_tree_path_new (); g_assert (G_NODE (iter->user_data)->parent != NULL); if (G_NODE (iter->user_data)->parent == G_NODE (tree_store->root)) { retval = gtk_tree_path_new (); tmp_node = G_NODE (tree_store->root)->children; } else { GtkTreeIter tmp_iter = *iter; tmp_iter.user_data = G_NODE (iter->user_data)->parent; retval = foo_tree_store_get_path (tree_model, &tmp_iter); tmp_node = G_NODE (iter->user_data)->parent->children; } if (retval == NULL) return NULL; if (tmp_node == NULL) { gtk_tree_path_free (retval); return NULL; } for (; tmp_node; tmp_node = tmp_node->next) { if (tmp_node == G_NODE (iter->user_data)) break; i++; } if (tmp_node == NULL) { /* We couldn't find node, meaning it's prolly not ours */ /* Perhaps I should do a g_return_if_fail here. */ gtk_tree_path_free (retval); return NULL; } gtk_tree_path_append_index (retval, i); return retval; } static void foo_tree_store_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value) { FooTreeStore *tree_store = (FooTreeStore *) tree_model; FooTreeDataList *list; gint tmp_column = column; g_return_if_fail (column < tree_store->n_columns); g_return_if_fail (VALID_ITER (iter, tree_store)); list = G_NODE (iter->user_data)->data; while (tmp_column-- > 0 && list) list = list->next; if (list) { _foo_tree_data_list_node_to_value (list, tree_store->column_headers[column], value); } else { /* We want to return an initialized but empty (default) value */ g_value_init (value, tree_store->column_headers[column]); } } static gboolean foo_tree_store_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter) { g_return_val_if_fail (iter->user_data != NULL, FALSE); g_return_val_if_fail (iter->stamp == FOO_TREE_STORE (tree_model)->stamp, FALSE); if (G_NODE (iter->user_data)->next) { iter->user_data = G_NODE (iter->user_data)->next; return TRUE; } else { iter->stamp = 0; return FALSE; } } static gboolean foo_tree_store_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent) { FooTreeStore *tree_store = (FooTreeStore *) tree_model; GNode *children; if (parent) g_return_val_if_fail (VALID_ITER (parent, tree_store), FALSE); if (parent) children = G_NODE (parent->user_data)->children; else children = G_NODE (tree_store->root)->children; if (children) { iter->stamp = tree_store->stamp; iter->user_data = children; return TRUE; } else { iter->stamp = 0; return FALSE; } } static gboolean foo_tree_store_iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter) { g_return_val_if_fail (iter->user_data != NULL, FALSE); g_return_val_if_fail (VALID_ITER (iter, tree_model), FALSE); return G_NODE (iter->user_data)->children != NULL; } static gint foo_tree_store_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter) { GNode *node; gint i = 0; g_return_val_if_fail (iter == NULL || iter->user_data != NULL, 0); if (iter == NULL) node = G_NODE (FOO_TREE_STORE (tree_model)->root)->children; else node = G_NODE (iter->user_data)->children; while (node) { i++; node = node->next; } return i; } static gboolean foo_tree_store_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n) { FooTreeStore *tree_store = (FooTreeStore *) tree_model; GNode *parent_node; GNode *child; g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE); if (parent == NULL) parent_node = tree_store->root; else parent_node = parent->user_data; child = g_node_nth_child (parent_node, n); if (child) { iter->user_data = child; iter->stamp = tree_store->stamp; return TRUE; } else { iter->stamp = 0; return FALSE; } } static gboolean foo_tree_store_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child) { FooTreeStore *tree_store = (FooTreeStore *) tree_model; GNode *parent; g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (VALID_ITER (child, tree_store), FALSE); parent = G_NODE (child->user_data)->parent; g_assert (parent != NULL); if (parent != tree_store->root) { iter->user_data = parent; iter->stamp = tree_store->stamp; return TRUE; } else { iter->stamp = 0; return FALSE; } } /* Does not emit a signal */ static gboolean foo_tree_store_real_set_value (FooTreeStore *tree_store, GtkTreeIter *iter, gint column, GValue *value, gboolean sort) { FooTreeDataList *list; FooTreeDataList *prev; gint old_column = column; GValue real_value = {0, }; gboolean converted = FALSE; gboolean retval = FALSE; if (! g_type_is_a (G_VALUE_TYPE (value), tree_store->column_headers[column])) { if (! (g_value_type_compatible (G_VALUE_TYPE (value), tree_store->column_headers[column]) && g_value_type_compatible (tree_store->column_headers[column], G_VALUE_TYPE (value)))) { g_warning ("%s: Unable to convert from %s to %s\n", G_STRLOC, g_type_name (G_VALUE_TYPE (value)), g_type_name (tree_store->column_headers[column])); return retval; } if (!g_value_transform (value, &real_value)) { g_warning ("%s: Unable to make conversion from %s to %s\n", G_STRLOC, g_type_name (G_VALUE_TYPE (value)), g_type_name (tree_store->column_headers[column])); g_value_unset (&real_value); return retval; } converted = TRUE; } prev = list = G_NODE (iter->user_data)->data; while (list != NULL) { if (column == 0) { if (converted) _foo_tree_data_list_value_to_node (list, &real_value); else _foo_tree_data_list_value_to_node (list, value); retval = TRUE; if (converted) g_value_unset (&real_value); if (sort && FOO_TREE_STORE_IS_SORTED (tree_store)) foo_tree_store_sort_iter_changed (tree_store, iter, old_column, TRUE); return retval; } column--; prev = list; list = list->next; } if (G_NODE (iter->user_data)->data == NULL) { G_NODE (iter->user_data)->data = list = _foo_tree_data_list_alloc (); list->next = NULL; } else { list = prev->next = _foo_tree_data_list_alloc (); list->next = NULL; } while (column != 0) { list->next = _foo_tree_data_list_alloc (); list = list->next; list->next = NULL; column --; } if (converted) _foo_tree_data_list_value_to_node (list, &real_value); else _foo_tree_data_list_value_to_node (list, value); retval = TRUE; if (converted) g_value_unset (&real_value); if (sort && FOO_TREE_STORE_IS_SORTED (tree_store)) foo_tree_store_sort_iter_changed (tree_store, iter, old_column, TRUE); return retval; } /** * foo_tree_store_set_value: * @tree_store: a #FooTreeStore * @iter: A valid #GtkTreeIter for the row being modified * @column: column number to modify * @value: new value for the cell * * Sets the data in the cell specified by @iter and @column. * The type of @value must be convertible to the type of the * column. * **/ void foo_tree_store_set_value (FooTreeStore *tree_store, GtkTreeIter *iter, gint column, GValue *value) { g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); g_return_if_fail (VALID_ITER (iter, tree_store)); g_return_if_fail (column >= 0 && column < tree_store->n_columns); g_return_if_fail (G_IS_VALUE (value)); if (foo_tree_store_real_set_value (tree_store, iter, column, value, TRUE)) { GtkTreePath *path; path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter); gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, iter); gtk_tree_path_free (path); } } static GtkTreeIterCompareFunc foo_tree_store_get_compare_func (FooTreeStore *tree_store) { GtkTreeIterCompareFunc func = NULL; if (FOO_TREE_STORE_IS_SORTED (tree_store)) { if (tree_store->sort_column_id != -1) { GtkTreeDataSortHeader *header; header = _foo_tree_data_list_get_header (tree_store->sort_list, tree_store->sort_column_id); g_return_val_if_fail (header != NULL, NULL); g_return_val_if_fail (header->func != NULL, NULL); func = header->func; } else { func = tree_store->default_sort_func; } } return func; } static void foo_tree_store_set_vector_internal (FooTreeStore *tree_store, GtkTreeIter *iter, gboolean *emit_signal, gboolean *maybe_need_sort, gint *columns, GValue *values, gint n_values) { gint i; GtkTreeIterCompareFunc func = NULL; func = foo_tree_store_get_compare_func (tree_store); if (func != _foo_tree_data_list_compare_func) *maybe_need_sort = TRUE; for (i = 0; i < n_values; i++) { *emit_signal = foo_tree_store_real_set_value (tree_store, iter, columns[i], &values[i], FALSE) || *emit_signal; if (func == _foo_tree_data_list_compare_func && columns[i] == tree_store->sort_column_id) *maybe_need_sort = TRUE; } } static void foo_tree_store_set_valist_internal (FooTreeStore *tree_store, GtkTreeIter *iter, gboolean *emit_signal, gboolean *maybe_need_sort, va_list var_args) { gint column; GtkTreeIterCompareFunc func = NULL; column = va_arg (var_args, gint); func = foo_tree_store_get_compare_func (tree_store); if (func != _foo_tree_data_list_compare_func) *maybe_need_sort = TRUE; while (column != -1) { GValue value = { 0, }; gchar *error = NULL; if (column < 0 || column >= tree_store->n_columns) { g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column); break; } g_value_init (&value, tree_store->column_headers[column]); G_VALUE_COLLECT (&value, var_args, 0, &error); if (error) { g_warning ("%s: %s", G_STRLOC, error); g_free (error); /* we purposely leak the value here, it might not be * in a sane state if an error condition occoured */ break; } *emit_signal = foo_tree_store_real_set_value (tree_store, iter, column, &value, FALSE) || *emit_signal; if (func == _foo_tree_data_list_compare_func && column == tree_store->sort_column_id) *maybe_need_sort = TRUE; g_value_unset (&value); column = va_arg (var_args, gint); } } /** * foo_tree_store_set_valuesv: * @tree_store: A #FooTreeStore * @iter: A valid #GtkTreeIter for the row being modified * @columns: an array of column numbers * @values: an array of GValues * @n_values: the length of the @columns and @values arrays * * A variant of foo_tree_store_set_valist() which takes * the columns and values as two arrays, instead of varargs. This * function is mainly intended for language bindings or in case * the number of columns to change is not known until run-time. * * Since: 2.12 **/ void foo_tree_store_set_valuesv (FooTreeStore *tree_store, GtkTreeIter *iter, gint *columns, GValue *values, gint n_values) { gboolean emit_signal = FALSE; gboolean maybe_need_sort = FALSE; g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); g_return_if_fail (VALID_ITER (iter, tree_store)); foo_tree_store_set_vector_internal (tree_store, iter, &emit_signal, &maybe_need_sort, columns, values, n_values); if (maybe_need_sort && FOO_TREE_STORE_IS_SORTED (tree_store)) foo_tree_store_sort_iter_changed (tree_store, iter, tree_store->sort_column_id, TRUE); if (emit_signal) { GtkTreePath *path; path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter); gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, iter); gtk_tree_path_free (path); } } /** * foo_tree_store_set_valist: * @tree_store: A #FooTreeStore * @iter: A valid #GtkTreeIter for the row being modified * @var_args: va_list of column/value pairs * * See foo_tree_store_set(); this version takes a va_list for * use by language bindings. * **/ void foo_tree_store_set_valist (FooTreeStore *tree_store, GtkTreeIter *iter, va_list var_args) { gboolean emit_signal = FALSE; gboolean maybe_need_sort = FALSE; g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); g_return_if_fail (VALID_ITER (iter, tree_store)); foo_tree_store_set_valist_internal (tree_store, iter, &emit_signal, &maybe_need_sort, var_args); if (maybe_need_sort && FOO_TREE_STORE_IS_SORTED (tree_store)) foo_tree_store_sort_iter_changed (tree_store, iter, tree_store->sort_column_id, TRUE); if (emit_signal) { if (g_signal_has_handler_pending (tree_store, tree_store->row_changed_id, 0, FALSE)) { GtkTreePath *path; path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter); gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, iter); gtk_tree_path_free (path); } } } /** * foo_tree_store_set: * @tree_store: A #FooTreeStore * @iter: A valid #GtkTreeIter for the row being modified * @Varargs: pairs of column number and value, terminated with -1 * * Sets the value of one or more cells in the row referenced by @iter. * The variable argument list should contain integer column numbers, * each column number followed by the value to be set. * The list is terminated by a -1. For example, to set column 0 with type * %G_TYPE_STRING to "Foo", you would write * foo_tree_store_set (store, iter, 0, "Foo", -1). * The value will be copied or referenced by the store if appropriate. **/ void foo_tree_store_set (FooTreeStore *tree_store, GtkTreeIter *iter, ...) { va_list var_args; va_start (var_args, iter); foo_tree_store_set_valist (tree_store, iter, var_args); va_end (var_args); } /** * foo_tree_store_remove: * @tree_store: A #FooTreeStore * @iter: A valid #GtkTreeIter * * Removes @iter from @tree_store. After being removed, @iter is set to the * next valid row at that level, or invalidated if it previously pointed to the * last one. * * Return value: %TRUE if @iter is still valid, %FALSE if not. **/ gboolean foo_tree_store_remove (FooTreeStore *tree_store, GtkTreeIter *iter) { GtkTreePath *path; GtkTreeIter new_iter = {0,}; GNode *parent; GNode *next_node; g_return_val_if_fail (FOO_IS_TREE_STORE (tree_store), FALSE); g_return_val_if_fail (VALID_ITER (iter, tree_store), FALSE); parent = G_NODE (iter->user_data)->parent; g_assert (parent != NULL); next_node = G_NODE (iter->user_data)->next; if (G_NODE (iter->user_data)->data) g_node_traverse (G_NODE (iter->user_data), G_POST_ORDER, G_TRAVERSE_ALL, -1, node_free, tree_store->column_headers); path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter); g_node_destroy (G_NODE (iter->user_data)); gtk_tree_model_row_deleted (GTK_TREE_MODEL (tree_store), path); if (parent != G_NODE (tree_store->root)) { /* child_toggled */ if (parent->children == NULL) { gtk_tree_path_up (path); new_iter.stamp = tree_store->stamp; new_iter.user_data = parent; gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, &new_iter); } } gtk_tree_path_free (path); /* revalidate iter */ if (next_node != NULL) { iter->stamp = tree_store->stamp; iter->user_data = next_node; return TRUE; } else { iter->stamp = 0; iter->user_data = NULL; } return FALSE; } /** * foo_tree_store_insert: * @tree_store: A #FooTreeStore * @iter: An unset #GtkTreeIter to set to the new row * @parent: A valid #GtkTreeIter, or %NULL * @position: position to insert the new row * * Creates a new row at @position. If parent is non-%NULL, then the row will be * made a child of @parent. Otherwise, the row will be created at the toplevel. * If @position is larger than the number of rows at that level, then the new * row will be inserted to the end of the list. @iter will be changed to point * to this new row. The row will be empty after this function is called. To * fill in values, you need to call foo_tree_store_set() or * foo_tree_store_set_value(). * **/ void foo_tree_store_insert (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent, gint position) { GNode *parent_node; GNode *new_node; g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); g_return_if_fail (iter != NULL); if (parent) g_return_if_fail (VALID_ITER (parent, tree_store)); if (parent) parent_node = parent->user_data; else parent_node = tree_store->root; tree_store->columns_dirty = TRUE; new_node = g_node_new (NULL); iter->stamp = tree_store->stamp; iter->user_data = new_node; g_node_insert (parent_node, position, new_node); if (g_signal_has_handler_pending (tree_store, tree_store->row_inserted_id, 0, FALSE) || g_signal_has_handler_pending (tree_store, tree_store->row_has_child_toggled_id, 0, FALSE)) { GtkTreePath *path; path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter); gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter); if (parent_node != tree_store->root) { if (new_node->prev == NULL && new_node->next == NULL) { gtk_tree_path_up (path); gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent); } } gtk_tree_path_free (path); } validate_tree ((FooTreeStore*)tree_store); } /** * foo_tree_store_insert_before: * @tree_store: A #FooTreeStore * @iter: An unset #GtkTreeIter to set to the new row * @parent: A valid #GtkTreeIter, or %NULL * @sibling: A valid #GtkTreeIter, or %NULL * * Inserts a new row before @sibling. If @sibling is %NULL, then the row will * be appended to @parent 's children. If @parent and @sibling are %NULL, then * the row will be appended to the toplevel. If both @sibling and @parent are * set, then @parent must be the parent of @sibling. When @sibling is set, * @parent is optional. * * @iter will be changed to point to this new row. The row will be empty after * this function is called. To fill in values, you need to call * foo_tree_store_set() or foo_tree_store_set_value(). * **/ void foo_tree_store_insert_before (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent, GtkTreeIter *sibling) { GtkTreePath *path; GNode *parent_node = NULL; GNode *new_node; g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); g_return_if_fail (iter != NULL); if (parent != NULL) g_return_if_fail (VALID_ITER (parent, tree_store)); if (sibling != NULL) g_return_if_fail (VALID_ITER (sibling, tree_store)); if (parent == NULL && sibling == NULL) parent_node = tree_store->root; else if (parent == NULL) parent_node = G_NODE (sibling->user_data)->parent; else if (sibling == NULL) parent_node = G_NODE (parent->user_data); else { g_return_if_fail (G_NODE (sibling->user_data)->parent == G_NODE (parent->user_data)); parent_node = G_NODE (parent->user_data); } tree_store->columns_dirty = TRUE; new_node = g_node_new (NULL); g_node_insert_before (parent_node, sibling ? G_NODE (sibling->user_data) : NULL, new_node); iter->stamp = tree_store->stamp; iter->user_data = new_node; path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter); gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter); if (parent_node != tree_store->root) { if (new_node->prev == NULL && new_node->next == NULL) { GtkTreeIter parent_iter; parent_iter.stamp = tree_store->stamp; parent_iter.user_data = parent_node; gtk_tree_path_up (path); gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, &parent_iter); } } gtk_tree_path_free (path); validate_tree (tree_store); } /** * foo_tree_store_insert_after: * @tree_store: A #FooTreeStore * @iter: An unset #GtkTreeIter to set to the new row * @parent: A valid #GtkTreeIter, or %NULL * @sibling: A valid #GtkTreeIter, or %NULL * * Inserts a new row after @sibling. If @sibling is %NULL, then the row will be * prepended to @parent 's children. If @parent and @sibling are %NULL, then * the row will be prepended to the toplevel. If both @sibling and @parent are * set, then @parent must be the parent of @sibling. When @sibling is set, * @parent is optional. * * @iter will be changed to point to this new row. The row will be empty after * this function is called. To fill in values, you need to call * foo_tree_store_set() or foo_tree_store_set_value(). * **/ void foo_tree_store_insert_after (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent, GtkTreeIter *sibling) { GtkTreePath *path; GNode *parent_node; GNode *new_node; g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); g_return_if_fail (iter != NULL); if (parent != NULL) g_return_if_fail (VALID_ITER (parent, tree_store)); if (sibling != NULL) g_return_if_fail (VALID_ITER (sibling, tree_store)); if (parent == NULL && sibling == NULL) parent_node = tree_store->root; else if (parent == NULL) parent_node = G_NODE (sibling->user_data)->parent; else if (sibling == NULL) parent_node = G_NODE (parent->user_data); else { g_return_if_fail (G_NODE (sibling->user_data)->parent == G_NODE (parent->user_data)); parent_node = G_NODE (parent->user_data); } tree_store->columns_dirty = TRUE; new_node = g_node_new (NULL); g_node_insert_after (parent_node, sibling ? G_NODE (sibling->user_data) : NULL, new_node); iter->stamp = tree_store->stamp; iter->user_data = new_node; path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter); gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter); if (parent_node != tree_store->root) { if (new_node->prev == NULL && new_node->next == NULL) { GtkTreeIter parent_iter; parent_iter.stamp = tree_store->stamp; parent_iter.user_data = parent_node; gtk_tree_path_up (path); gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, &parent_iter); } } gtk_tree_path_free (path); validate_tree (tree_store); } /** * foo_tree_store_insert_with_values: * @tree_store: A #FooTreeStore * @iter: An unset #GtkTreeIter to set the new row, or %NULL. * @parent: A valid #GtkTreeIter, or %NULL * @position: position to insert the new row * @Varargs: pairs of column number and value, terminated with -1 * * Creates a new row at @position. @iter will be changed to point to this * new row. If @position is larger than the number of rows on the list, then * the new row will be appended to the list. The row will be filled with * the values given to this function. * * Calling * foo_tree_store_insert_with_values (tree_store, iter, position, ...) * has the same effect as calling * |[ * foo_tree_store_insert (tree_store, iter, position); * foo_tree_store_set (tree_store, iter, ...); * ]| * with the different that the former will only emit a row_inserted signal, * while the latter will emit row_inserted, row_changed and if the tree store * is sorted, rows_reordered. Since emitting the rows_reordered signal * repeatedly can affect the performance of the program, * foo_tree_store_insert_with_values() should generally be preferred when * inserting rows in a sorted tree store. * * Since: 2.10 */ void foo_tree_store_insert_with_values (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent, gint position, ...) { GtkTreePath *path; GNode *parent_node; GNode *new_node; GtkTreeIter tmp_iter; va_list var_args; gboolean changed = FALSE; gboolean maybe_need_sort = FALSE; g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); if (!iter) iter = &tmp_iter; if (parent) g_return_if_fail (VALID_ITER (parent, tree_store)); if (parent) parent_node = parent->user_data; else parent_node = tree_store->root; tree_store->columns_dirty = TRUE; new_node = g_node_new (NULL); iter->stamp = tree_store->stamp; iter->user_data = new_node; g_node_insert (parent_node, position, new_node); va_start (var_args, position); foo_tree_store_set_valist_internal (tree_store, iter, &changed, &maybe_need_sort, var_args); va_end (var_args); if (maybe_need_sort && FOO_TREE_STORE_IS_SORTED (tree_store)) foo_tree_store_sort_iter_changed (tree_store, iter, tree_store->sort_column_id, FALSE); path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter); gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter); if (parent_node != tree_store->root) { if (new_node->prev == NULL && new_node->next == NULL) { gtk_tree_path_up (path); gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent); } } gtk_tree_path_free (path); validate_tree ((FooTreeStore *)tree_store); } /** * foo_tree_store_insert_with_valuesv: * @tree_store: A #FooTreeStore * @iter: An unset #GtkTreeIter to set the new row, or %NULL. * @parent: A valid #GtkTreeIter, or %NULL * @position: position to insert the new row * @columns: an array of column numbers * @values: an array of GValues * @n_values: the length of the @columns and @values arrays * * A variant of foo_tree_store_insert_with_values() which takes * the columns and values as two arrays, instead of varargs. This * function is mainly intended for language bindings. * * Since: 2.10 */ void foo_tree_store_insert_with_valuesv (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent, gint position, gint *columns, GValue *values, gint n_values) { GtkTreePath *path; GNode *parent_node; GNode *new_node; GtkTreeIter tmp_iter; gboolean changed = FALSE; gboolean maybe_need_sort = FALSE; g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); if (!iter) iter = &tmp_iter; if (parent) g_return_if_fail (VALID_ITER (parent, tree_store)); if (parent) parent_node = parent->user_data; else parent_node = tree_store->root; tree_store->columns_dirty = TRUE; new_node = g_node_new (NULL); iter->stamp = tree_store->stamp; iter->user_data = new_node; g_node_insert (parent_node, position, new_node); foo_tree_store_set_vector_internal (tree_store, iter, &changed, &maybe_need_sort, columns, values, n_values); if (maybe_need_sort && FOO_TREE_STORE_IS_SORTED (tree_store)) foo_tree_store_sort_iter_changed (tree_store, iter, tree_store->sort_column_id, FALSE); path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter); gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter); if (parent_node != tree_store->root) { if (new_node->prev == NULL && new_node->next == NULL) { gtk_tree_path_up (path); gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent); } } gtk_tree_path_free (path); validate_tree ((FooTreeStore *)tree_store); } /** * foo_tree_store_prepend: * @tree_store: A #FooTreeStore * @iter: An unset #GtkTreeIter to set to the prepended row * @parent: A valid #GtkTreeIter, or %NULL * * Prepends a new row to @tree_store. If @parent is non-%NULL, then it will prepend * the new row before the first child of @parent, otherwise it will prepend a row * to the top level. @iter will be changed to point to this new row. The row * will be empty after this function is called. To fill in values, you need to * call foo_tree_store_set() or foo_tree_store_set_value(). **/ void foo_tree_store_prepend (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent) { GNode *parent_node; g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); g_return_if_fail (iter != NULL); if (parent != NULL) g_return_if_fail (VALID_ITER (parent, tree_store)); tree_store->columns_dirty = TRUE; if (parent == NULL) parent_node = tree_store->root; else parent_node = parent->user_data; if (parent_node->children == NULL) { GtkTreePath *path; iter->stamp = tree_store->stamp; iter->user_data = g_node_new (NULL); g_node_prepend (parent_node, G_NODE (iter->user_data)); path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter); gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter); if (parent_node != tree_store->root) { gtk_tree_path_up (path); gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent); } gtk_tree_path_free (path); } else { foo_tree_store_insert_after (tree_store, iter, parent, NULL); } validate_tree (tree_store); } /** * foo_tree_store_append: * @tree_store: A #FooTreeStore * @iter: An unset #GtkTreeIter to set to the appended row * @parent: A valid #GtkTreeIter, or %NULL * * Appends a new row to @tree_store. If @parent is non-%NULL, then it will append the * new row after the last child of @parent, otherwise it will append a row to * the top level. @iter will be changed to point to this new row. The row will * be empty after this function is called. To fill in values, you need to call * foo_tree_store_set() or foo_tree_store_set_value(). **/ void foo_tree_store_append (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent) { GNode *parent_node; g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); g_return_if_fail (iter != NULL); if (parent != NULL) g_return_if_fail (VALID_ITER (parent, tree_store)); if (parent == NULL) parent_node = tree_store->root; else parent_node = parent->user_data; tree_store->columns_dirty = TRUE; if (parent_node->children == NULL) { GtkTreePath *path; iter->stamp = tree_store->stamp; iter->user_data = g_node_new (NULL); g_node_append (parent_node, G_NODE (iter->user_data)); path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter); gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter); if (parent_node != tree_store->root) { gtk_tree_path_up (path); gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent); } gtk_tree_path_free (path); } else { foo_tree_store_insert_before (tree_store, iter, parent, NULL); } validate_tree (tree_store); } /** * foo_tree_store_is_ancestor: * @tree_store: A #FooTreeStore * @iter: A valid #GtkTreeIter * @descendant: A valid #GtkTreeIter * * Returns %TRUE if @iter is an ancestor of @descendant. That is, @iter is the * parent (or grandparent or great-grandparent) of @descendant. * * Return value: %TRUE, if @iter is an ancestor of @descendant **/ gboolean foo_tree_store_is_ancestor (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *descendant) { g_return_val_if_fail (FOO_IS_TREE_STORE (tree_store), FALSE); g_return_val_if_fail (VALID_ITER (iter, tree_store), FALSE); g_return_val_if_fail (VALID_ITER (descendant, tree_store), FALSE); return g_node_is_ancestor (G_NODE (iter->user_data), G_NODE (descendant->user_data)); } /** * foo_tree_store_iter_depth: * @tree_store: A #FooTreeStore * @iter: A valid #GtkTreeIter * * Returns the depth of @iter. This will be 0 for anything on the root level, 1 * for anything down a level, etc. * * Return value: The depth of @iter **/ gint foo_tree_store_iter_depth (FooTreeStore *tree_store, GtkTreeIter *iter) { g_return_val_if_fail (FOO_IS_TREE_STORE (tree_store), 0); g_return_val_if_fail (VALID_ITER (iter, tree_store), 0); return g_node_depth (G_NODE (iter->user_data)) - 2; } /* simple ripoff from g_node_traverse_post_order */ static gboolean foo_tree_store_clear_traverse (GNode *node, FooTreeStore *store) { GtkTreeIter iter; if (node->children) { GNode *child; child = node->children; while (child) { register GNode *current; current = child; child = current->next; if (foo_tree_store_clear_traverse (current, store)) return TRUE; } if (node->parent) { iter.stamp = store->stamp; iter.user_data = node; foo_tree_store_remove (store, &iter); } } else if (node->parent) { iter.stamp = store->stamp; iter.user_data = node; foo_tree_store_remove (store, &iter); } return FALSE; } static void foo_tree_store_increment_stamp (FooTreeStore *tree_store) { do { tree_store->stamp++; } while (tree_store->stamp == 0); } /** * foo_tree_store_clear: * @tree_store: a #FooTreeStore * * Removes all rows from @tree_store **/ void foo_tree_store_clear (FooTreeStore *tree_store) { g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); foo_tree_store_clear_traverse (tree_store->root, tree_store); foo_tree_store_increment_stamp (tree_store); } static gboolean foo_tree_store_iter_is_valid_helper (GtkTreeIter *iter, GNode *first) { GNode *node; node = first; do { if (node == iter->user_data) return TRUE; if (node->children) if (foo_tree_store_iter_is_valid_helper (iter, node->children)) return TRUE; node = node->next; } while (node); return FALSE; } /** * foo_tree_store_iter_is_valid: * @tree_store: A #FooTreeStore. * @iter: A #GtkTreeIter. * * WARNING: This function is slow. Only use it for debugging and/or testing * purposes. * * Checks if the given iter is a valid iter for this #FooTreeStore. * * Return value: %TRUE if the iter is valid, %FALSE if the iter is invalid. * * Since: 2.2 **/ gboolean foo_tree_store_iter_is_valid (FooTreeStore *tree_store, GtkTreeIter *iter) { g_return_val_if_fail (FOO_IS_TREE_STORE (tree_store), FALSE); g_return_val_if_fail (iter != NULL, FALSE); if (!VALID_ITER (iter, tree_store)) return FALSE; return foo_tree_store_iter_is_valid_helper (iter, tree_store->root); } /* DND */ static gboolean real_foo_tree_store_row_draggable (GtkTreeDragSource *drag_source, GtkTreePath *path) { return TRUE; } static gboolean foo_tree_store_drag_data_delete (GtkTreeDragSource *drag_source, GtkTreePath *path) { GtkTreeIter iter; if (foo_tree_store_get_iter (GTK_TREE_MODEL (drag_source), &iter, path)) { foo_tree_store_remove (FOO_TREE_STORE (drag_source), &iter); return TRUE; } else { return FALSE; } } static gboolean foo_tree_store_drag_data_get (GtkTreeDragSource *drag_source, GtkTreePath *path, GtkSelectionData *selection_data) { /* Note that we don't need to handle the GTK_TREE_MODEL_ROW * target, because the default handler does it for us, but * we do anyway for the convenience of someone maybe overriding the * default handler. */ if (gtk_tree_set_row_drag_data (selection_data, GTK_TREE_MODEL (drag_source), path)) { return TRUE; } else { /* FIXME handle text targets at least. */ } return FALSE; } static void copy_node_data (FooTreeStore *tree_store, GtkTreeIter *src_iter, GtkTreeIter *dest_iter) { FooTreeDataList *dl = G_NODE (src_iter->user_data)->data; FooTreeDataList *copy_head = NULL; FooTreeDataList *copy_prev = NULL; FooTreeDataList *copy_iter = NULL; GtkTreePath *path; gint col; col = 0; while (dl) { copy_iter = _foo_tree_data_list_node_copy (dl, tree_store->column_headers[col]); if (copy_head == NULL) copy_head = copy_iter; if (copy_prev) copy_prev->next = copy_iter; copy_prev = copy_iter; dl = dl->next; ++col; } G_NODE (dest_iter->user_data)->data = copy_head; path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), dest_iter); gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, dest_iter); gtk_tree_path_free (path); } static void recursive_node_copy (FooTreeStore *tree_store, GtkTreeIter *src_iter, GtkTreeIter *dest_iter) { GtkTreeIter child; GtkTreeModel *model; model = GTK_TREE_MODEL (tree_store); copy_node_data (tree_store, src_iter, dest_iter); if (foo_tree_store_iter_children (model, &child, src_iter)) { /* Need to create children and recurse. Note our * dependence on persistent iterators here. */ do { GtkTreeIter copy; /* Gee, a really slow algorithm... ;-) FIXME */ foo_tree_store_append (tree_store, ©, dest_iter); recursive_node_copy (tree_store, &child, ©); } while (foo_tree_store_iter_next (model, &child)); } } static gboolean foo_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data) { GtkTreeModel *tree_model; FooTreeStore *tree_store; GtkTreeModel *src_model = NULL; GtkTreePath *src_path = NULL; gboolean retval = FALSE; tree_model = GTK_TREE_MODEL (drag_dest); tree_store = FOO_TREE_STORE (drag_dest); validate_tree (tree_store); if (gtk_tree_get_row_drag_data (selection_data, &src_model, &src_path) && src_model == tree_model) { /* Copy the given row to a new position */ GtkTreeIter src_iter; GtkTreeIter dest_iter; GtkTreePath *prev; if (!foo_tree_store_get_iter (src_model, &src_iter, src_path)) { goto out; } /* Get the path to insert _after_ (dest is the path to insert _before_) */ prev = gtk_tree_path_copy (dest); if (!gtk_tree_path_prev (prev)) { GtkTreeIter dest_parent; GtkTreePath *parent; GtkTreeIter *dest_parent_p; /* dest was the first spot at the current depth; which means * we are supposed to prepend. */ /* Get the parent, NULL if parent is the root */ dest_parent_p = NULL; parent = gtk_tree_path_copy (dest); if (gtk_tree_path_up (parent) && gtk_tree_path_get_depth (parent) > 0) { foo_tree_store_get_iter (tree_model, &dest_parent, parent); dest_parent_p = &dest_parent; } gtk_tree_path_free (parent); parent = NULL; foo_tree_store_prepend (tree_store, &dest_iter, dest_parent_p); retval = TRUE; } else { if (foo_tree_store_get_iter (tree_model, &dest_iter, prev)) { GtkTreeIter tmp_iter = dest_iter; foo_tree_store_insert_after (tree_store, &dest_iter, NULL, &tmp_iter); retval = TRUE; } } gtk_tree_path_free (prev); /* If we succeeded in creating dest_iter, walk src_iter tree branch, * duplicating it below dest_iter. */ if (retval) { recursive_node_copy (tree_store, &src_iter, &dest_iter); } } else { /* FIXME maybe add some data targets eventually, or handle text * targets in the simple case. */ } out: if (src_path) gtk_tree_path_free (src_path); return retval; } static gboolean foo_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, GtkSelectionData *selection_data) { GtkTreeModel *src_model = NULL; GtkTreePath *src_path = NULL; GtkTreePath *tmp = NULL; gboolean retval = FALSE; /* don't accept drops if the tree has been sorted */ if (FOO_TREE_STORE_IS_SORTED (drag_dest)) return FALSE; if (!gtk_tree_get_row_drag_data (selection_data, &src_model, &src_path)) goto out; /* can only drag to ourselves */ if (src_model != GTK_TREE_MODEL (drag_dest)) goto out; /* Can't drop into ourself. */ if (gtk_tree_path_is_ancestor (src_path, dest_path)) goto out; /* Can't drop if dest_path's parent doesn't exist */ { GtkTreeIter iter; if (gtk_tree_path_get_depth (dest_path) > 1) { tmp = gtk_tree_path_copy (dest_path); gtk_tree_path_up (tmp); if (!foo_tree_store_get_iter (GTK_TREE_MODEL (drag_dest), &iter, tmp)) goto out; } } /* Can otherwise drop anywhere. */ retval = TRUE; out: if (src_path) gtk_tree_path_free (src_path); if (tmp) gtk_tree_path_free (tmp); return retval; } /* Sorting and reordering */ typedef struct _SortTuple { gint offset; GNode *node; } SortTuple; /* Reordering */ static gint foo_tree_store_reorder_func (gconstpointer a, gconstpointer b, gpointer user_data) { SortTuple *a_reorder; SortTuple *b_reorder; a_reorder = (SortTuple *)a; b_reorder = (SortTuple *)b; if (a_reorder->offset < b_reorder->offset) return -1; if (a_reorder->offset > b_reorder->offset) return 1; return 0; } /** * foo_tree_store_reorder: * @tree_store: A #FooTreeStore. * @parent: A #GtkTreeIter. * @new_order: an array of integers mapping the new position of each child * to its old position before the re-ordering, * i.e. @new_order[newpos] = oldpos. * * Reorders the children of @parent in @tree_store to follow the order * indicated by @new_order. Note that this function only works with * unsorted stores. * * Since: 2.2 **/ void foo_tree_store_reorder (FooTreeStore *tree_store, GtkTreeIter *parent, gint *new_order) { gint i, length = 0; GNode *level, *node; GtkTreePath *path; SortTuple *sort_array; g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); g_return_if_fail (!FOO_TREE_STORE_IS_SORTED (tree_store)); g_return_if_fail (parent == NULL || VALID_ITER (parent, tree_store)); g_return_if_fail (new_order != NULL); if (!parent) level = G_NODE (tree_store->root)->children; else level = G_NODE (parent->user_data)->children; /* count nodes */ node = level; while (node) { length++; node = node->next; } /* set up sortarray */ sort_array = g_new (SortTuple, length); node = level; for (i = 0; i < length; i++) { sort_array[new_order[i]].offset = i; sort_array[i].node = node; node = node->next; } g_qsort_with_data (sort_array, length, sizeof (SortTuple), foo_tree_store_reorder_func, NULL); /* fix up level */ for (i = 0; i < length - 1; i++) { sort_array[i].node->next = sort_array[i+1].node; sort_array[i+1].node->prev = sort_array[i].node; } sort_array[length-1].node->next = NULL; sort_array[0].node->prev = NULL; if (parent) G_NODE (parent->user_data)->children = sort_array[0].node; else G_NODE (tree_store->root)->children = sort_array[0].node; /* emit signal */ if (parent) path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), parent); else path = gtk_tree_path_new (); gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store), path, parent, new_order); gtk_tree_path_free (path); g_free (sort_array); } /** * foo_tree_store_swap: * @tree_store: A #FooTreeStore. * @a: A #GtkTreeIter. * @b: Another #GtkTreeIter. * * Swaps @a and @b in the same level of @tree_store. Note that this function * only works with unsorted stores. * * Since: 2.2 **/ void foo_tree_store_swap (FooTreeStore *tree_store, GtkTreeIter *a, GtkTreeIter *b) { GNode *tmp, *node_a, *node_b, *parent_node; GNode *a_prev, *a_next, *b_prev, *b_next; gint i, a_count, b_count, length, *order; GtkTreePath *path_a, *path_b; GtkTreeIter parent; g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); g_return_if_fail (VALID_ITER (a, tree_store)); g_return_if_fail (VALID_ITER (b, tree_store)); node_a = G_NODE (a->user_data); node_b = G_NODE (b->user_data); /* basic sanity checking */ if (node_a == node_b) return; path_a = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), a); path_b = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), b); g_return_if_fail (path_a && path_b); gtk_tree_path_up (path_a); gtk_tree_path_up (path_b); if (gtk_tree_path_get_depth (path_a) == 0 || gtk_tree_path_get_depth (path_b) == 0) { if (gtk_tree_path_get_depth (path_a) != gtk_tree_path_get_depth (path_b)) { gtk_tree_path_free (path_a); gtk_tree_path_free (path_b); g_warning ("Given children are not in the same level\n"); return; } parent_node = G_NODE (tree_store->root); } else { if (gtk_tree_path_compare (path_a, path_b)) { gtk_tree_path_free (path_a); gtk_tree_path_free (path_b); g_warning ("Given children don't have a common parent\n"); return; } foo_tree_store_get_iter (GTK_TREE_MODEL (tree_store), &parent, path_a); parent_node = G_NODE (parent.user_data); } gtk_tree_path_free (path_b); /* old links which we have to keep around */ a_prev = node_a->prev; a_next = node_a->next; b_prev = node_b->prev; b_next = node_b->next; /* fix up links if the nodes are next to eachother */ if (a_prev == node_b) a_prev = node_a; if (a_next == node_b) a_next = node_a; if (b_prev == node_a) b_prev = node_b; if (b_next == node_a) b_next = node_b; /* counting nodes */ tmp = parent_node->children; i = a_count = b_count = 0; while (tmp) { if (tmp == node_a) a_count = i; if (tmp == node_b) b_count = i; tmp = tmp->next; i++; } length = i; /* hacking the tree */ if (!a_prev) parent_node->children = node_b; else a_prev->next = node_b; if (a_next) a_next->prev = node_b; if (!b_prev) parent_node->children = node_a; else b_prev->next = node_a; if (b_next) b_next->prev = node_a; node_a->prev = b_prev; node_a->next = b_next; node_b->prev = a_prev; node_b->next = a_next; /* emit signal */ order = g_new (gint, length); for (i = 0; i < length; i++) if (i == a_count) order[i] = b_count; else if (i == b_count) order[i] = a_count; else order[i] = i; gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store), path_a, parent_node == tree_store->root ? NULL : &parent, order); gtk_tree_path_free (path_a); g_free (order); } /* WARNING: this function is *incredibly* fragile. Please smashtest after * making changes here. * -Kris */ static void foo_tree_store_move (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *position, gboolean before) { GNode *parent, *node, *a, *b, *tmp, *tmp_a, *tmp_b; gint old_pos, new_pos, length, i, *order; GtkTreePath *path = NULL, *tmppath, *pos_path = NULL; GtkTreeIter parent_iter, dst_a, dst_b; gint depth = 0; gboolean handle_b = TRUE; g_return_if_fail (FOO_IS_TREE_STORE (tree_store)); g_return_if_fail (!FOO_TREE_STORE_IS_SORTED (tree_store)); g_return_if_fail (VALID_ITER (iter, tree_store)); if (position) g_return_if_fail (VALID_ITER (position, tree_store)); a = b = NULL; /* sanity checks */ if (position) { path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter); pos_path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), position); /* if before: * moving the iter before path or "path + 1" doesn't make sense * else * moving the iter before path or "path - 1" doesn't make sense */ if (!gtk_tree_path_compare (path, pos_path)) goto free_paths_and_out; if (before) gtk_tree_path_next (path); else gtk_tree_path_prev (path); if (!gtk_tree_path_compare (path, pos_path)) goto free_paths_and_out; if (before) gtk_tree_path_prev (path); else gtk_tree_path_next (path); if (gtk_tree_path_get_depth (path) != gtk_tree_path_get_depth (pos_path)) { g_warning ("Given children are not in the same level\n"); goto free_paths_and_out; } tmppath = gtk_tree_path_copy (pos_path); gtk_tree_path_up (path); gtk_tree_path_up (tmppath); if (gtk_tree_path_get_depth (path) > 0 && gtk_tree_path_compare (path, tmppath)) { g_warning ("Given children are not in the same level\n"); gtk_tree_path_free (tmppath); goto free_paths_and_out; } gtk_tree_path_free (tmppath); } if (!path) { path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter); gtk_tree_path_up (path); } depth = gtk_tree_path_get_depth (path); if (depth) { foo_tree_store_get_iter (GTK_TREE_MODEL (tree_store), &parent_iter, path); parent = G_NODE (parent_iter.user_data); } else parent = G_NODE (tree_store->root); /* yes, I know that this can be done shorter, but I'm doing it this way * so the code is also maintainable */ if (before && position) { b = G_NODE (position->user_data); if (gtk_tree_path_get_indices (pos_path)[gtk_tree_path_get_depth (pos_path) - 1] > 0) { gtk_tree_path_prev (pos_path); if (foo_tree_store_get_iter (GTK_TREE_MODEL (tree_store), &dst_a, pos_path)) a = G_NODE (dst_a.user_data); else a = NULL; gtk_tree_path_next (pos_path); } /* if b is NULL, a is NULL too -- we are at the beginning of the list * yes and we leak memory here ... */ g_return_if_fail (b); } else if (before && !position) { /* move before without position is appending */ a = NULL; b = NULL; } else /* !before */ { if (position) a = G_NODE (position->user_data); else a = NULL; if (position) { gtk_tree_path_next (pos_path); if (foo_tree_store_get_iter (GTK_TREE_MODEL (tree_store), &dst_b, pos_path)) b = G_NODE (dst_b.user_data); else b = NULL; gtk_tree_path_prev (pos_path); } else { /* move after without position is prepending */ if (depth) foo_tree_store_iter_children (GTK_TREE_MODEL (tree_store), &dst_b, &parent_iter); else foo_tree_store_iter_children (GTK_TREE_MODEL (tree_store), &dst_b, NULL); b = G_NODE (dst_b.user_data); } /* if a is NULL, b is NULL too -- we are at the end of the list * yes and we leak memory here ... */ if (position) g_return_if_fail (a); } /* counting nodes */ tmp = parent->children; length = old_pos = 0; while (tmp) { if (tmp == iter->user_data) old_pos = length; tmp = tmp->next; length++; } /* remove node from list */ node = G_NODE (iter->user_data); tmp_a = node->prev; tmp_b = node->next; if (tmp_a) tmp_a->next = tmp_b; else parent->children = tmp_b; if (tmp_b) tmp_b->prev = tmp_a; /* and reinsert the node */ if (a) { tmp = a->next; a->next = node; node->next = tmp; node->prev = a; } else if (!a && !before) { tmp = parent->children; node->prev = NULL; parent->children = node; node->next = tmp; if (tmp) tmp->prev = node; handle_b = FALSE; } else if (!a && before) { if (!position) { node->parent = NULL; node->next = node->prev = NULL; /* before with sibling = NULL appends */ g_node_insert_before (parent, NULL, node); } else { node->parent = NULL; node->next = node->prev = NULL; /* after with sibling = NULL prepends */ g_node_insert_after (parent, NULL, node); } handle_b = FALSE; } if (handle_b) { if (b) { tmp = b->prev; b->prev = node; node->prev = tmp; node->next = b; } else if (!(!a && before)) /* !a && before is completely handled above */ node->next = NULL; } /* emit signal */ if (position) new_pos = gtk_tree_path_get_indices (pos_path)[gtk_tree_path_get_depth (pos_path)-1]; else if (before) { if (depth) new_pos = foo_tree_store_iter_n_children (GTK_TREE_MODEL (tree_store), &parent_iter) - 1; else new_pos = foo_tree_store_iter_n_children (GTK_TREE_MODEL (tree_store), NULL) - 1; } else new_pos = 0; if (new_pos > old_pos) { if (before && position) new_pos--; } else { if (!before && position) new_pos++; } order = g_new (gint, length); if (new_pos > old_pos) { for (i = 0; i < length; i++) if (i < old_pos) order[i] = i; else if (i >= old_pos && i < new_pos) order[i] = i + 1; else if (i == new_pos) order[i] = old_pos; else order[i] = i; } else { for (i = 0; i < length; i++) if (i == new_pos) order[i] = old_pos; else if (i > new_pos && i <= old_pos) order[i] = i - 1; else order[i] = i; } if (depth) { tmppath = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), &parent_iter); gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store), tmppath, &parent_iter, order); } else { tmppath = gtk_tree_path_new (); gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store), tmppath, NULL, order); } gtk_tree_path_free (tmppath); gtk_tree_path_free (path); if (position) gtk_tree_path_free (pos_path); g_free (order); return; free_paths_and_out: gtk_tree_path_free (path); gtk_tree_path_free (pos_path); } /** * foo_tree_store_move_before: * @tree_store: A #FooTreeStore. * @iter: A #GtkTreeIter. * @position: A #GtkTreeIter or %NULL. * * Moves @iter in @tree_store to the position before @position. @iter and * @position should be in the same level. Note that this function only * works with unsorted stores. If @position is %NULL, @iter will be * moved to the end of the level. * * Since: 2.2 **/ void foo_tree_store_move_before (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *position) { foo_tree_store_move (tree_store, iter, position, TRUE); } /** * foo_tree_store_move_after: * @tree_store: A #FooTreeStore. * @iter: A #GtkTreeIter. * @position: A #GtkTreeIter. * * Moves @iter in @tree_store to the position after @position. @iter and * @position should be in the same level. Note that this function only * works with unsorted stores. If @position is %NULL, @iter will be moved * to the start of the level. * * Since: 2.2 **/ void foo_tree_store_move_after (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *position) { foo_tree_store_move (tree_store, iter, position, FALSE); } /* Sorting */ static gint foo_tree_store_compare_func (gconstpointer a, gconstpointer b, gpointer user_data) { FooTreeStore *tree_store = user_data; GNode *node_a; GNode *node_b; GtkTreeIterCompareFunc func; gpointer data; GtkTreeIter iter_a; GtkTreeIter iter_b; gint retval; if (tree_store->sort_column_id != -1) { GtkTreeDataSortHeader *header; header = _foo_tree_data_list_get_header (tree_store->sort_list, tree_store->sort_column_id); g_return_val_if_fail (header != NULL, 0); g_return_val_if_fail (header->func != NULL, 0); func = header->func; data = header->data; } else { g_return_val_if_fail (tree_store->default_sort_func != NULL, 0); func = tree_store->default_sort_func; data = tree_store->default_sort_data; } node_a = ((SortTuple *) a)->node; node_b = ((SortTuple *) b)->node; iter_a.stamp = tree_store->stamp; iter_a.user_data = node_a; iter_b.stamp = tree_store->stamp; iter_b.user_data = node_b; retval = (* func) (GTK_TREE_MODEL (user_data), &iter_a, &iter_b, data); if (tree_store->order == GTK_SORT_DESCENDING) { if (retval > 0) retval = -1; else if (retval < 0) retval = 1; } return retval; } static void foo_tree_store_sort_helper (FooTreeStore *tree_store, GNode *parent, gboolean recurse) { GtkTreeIter iter; GArray *sort_array; GNode *node; GNode *tmp_node; gint list_length; gint i; gint *new_order; GtkTreePath *path; node = parent->children; if (node == NULL || node->next == NULL) { if (recurse && node && node->children) foo_tree_store_sort_helper (tree_store, node, TRUE); return; } list_length = 0; for (tmp_node = node; tmp_node; tmp_node = tmp_node->next) list_length++; sort_array = g_array_sized_new (FALSE, FALSE, sizeof (SortTuple), list_length); i = 0; for (tmp_node = node; tmp_node; tmp_node = tmp_node->next) { SortTuple tuple; tuple.offset = i; tuple.node = tmp_node; g_array_append_val (sort_array, tuple); i++; } /* Sort the array */ g_array_sort_with_data (sort_array, foo_tree_store_compare_func, tree_store); for (i = 0; i < list_length - 1; i++) { g_array_index (sort_array, SortTuple, i).node->next = g_array_index (sort_array, SortTuple, i + 1).node; g_array_index (sort_array, SortTuple, i + 1).node->prev = g_array_index (sort_array, SortTuple, i).node; } g_array_index (sort_array, SortTuple, list_length - 1).node->next = NULL; g_array_index (sort_array, SortTuple, 0).node->prev = NULL; parent->children = g_array_index (sort_array, SortTuple, 0).node; /* Let the world know about our new order */ new_order = g_new (gint, list_length); for (i = 0; i < list_length; i++) new_order[i] = g_array_index (sort_array, SortTuple, i).offset; iter.stamp = tree_store->stamp; iter.user_data = parent; if (g_signal_has_handler_pending (tree_store, tree_store->row_inserted_id, 0, FALSE)) { path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), &iter); gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store), path, &iter, new_order); gtk_tree_path_free (path); } g_free (new_order); g_array_free (sort_array, TRUE); if (recurse) { for (tmp_node = parent->children; tmp_node; tmp_node = tmp_node->next) { if (tmp_node->children) foo_tree_store_sort_helper (tree_store, tmp_node, TRUE); } } } static void foo_tree_store_sort (FooTreeStore *tree_store) { if (!FOO_TREE_STORE_IS_SORTED (tree_store)) return; if (tree_store->sort_column_id != -1) { GtkTreeDataSortHeader *header = NULL; header = _foo_tree_data_list_get_header (tree_store->sort_list, tree_store->sort_column_id); /* We want to make sure that we have a function */ g_return_if_fail (header != NULL); g_return_if_fail (header->func != NULL); } else { g_return_if_fail (tree_store->default_sort_func != NULL); } foo_tree_store_sort_helper (tree_store, G_NODE (tree_store->root), TRUE); } static void foo_tree_store_sort_iter_changed (FooTreeStore *tree_store, GtkTreeIter *iter, gint column, gboolean emit_signal) { GNode *prev = NULL; GNode *next = NULL; GNode *node; GtkTreePath *tmp_path; GtkTreeIter tmp_iter; gint cmp_a = 0; gint cmp_b = 0; gint i; gint old_location; gint new_location; gint *new_order; gint length; GtkTreeIterCompareFunc func; gpointer data; g_return_if_fail (G_NODE (iter->user_data)->parent != NULL); tmp_iter.stamp = tree_store->stamp; if (tree_store->sort_column_id != -1) { GtkTreeDataSortHeader *header; header = _foo_tree_data_list_get_header (tree_store->sort_list, tree_store->sort_column_id); g_return_if_fail (header != NULL); g_return_if_fail (header->func != NULL); func = header->func; data = header->data; } else { g_return_if_fail (tree_store->default_sort_func != NULL); func = tree_store->default_sort_func; data = tree_store->default_sort_data; } /* If it's the built in function, we don't sort. */ if (func == _foo_tree_data_list_compare_func && tree_store->sort_column_id != column) return; old_location = 0; node = G_NODE (iter->user_data)->parent->children; /* First we find the iter, its prev, and its next */ while (node) { if (node == G_NODE (iter->user_data)) break; old_location++; node = node->next; } g_assert (node != NULL); prev = node->prev; next = node->next; /* Check the common case, where we don't need to sort it moved. */ if (prev != NULL) { tmp_iter.user_data = prev; cmp_a = (* func) (GTK_TREE_MODEL (tree_store), &tmp_iter, iter, data); } if (next != NULL) { tmp_iter.user_data = next; cmp_b = (* func) (GTK_TREE_MODEL (tree_store), iter, &tmp_iter, data); } if (tree_store->order == GTK_SORT_DESCENDING) { if (cmp_a < 0) cmp_a = 1; else if (cmp_a > 0) cmp_a = -1; if (cmp_b < 0) cmp_b = 1; else if (cmp_b > 0) cmp_b = -1; } if (prev == NULL && cmp_b <= 0) return; else if (next == NULL && cmp_a <= 0) return; else if (prev != NULL && next != NULL && cmp_a <= 0 && cmp_b <= 0) return; /* We actually need to sort it */ /* First, remove the old link. */ if (prev) prev->next = next; else node->parent->children = next; if (next) next->prev = prev; node->prev = NULL; node->next = NULL; /* FIXME: as an optimization, we can potentially start at next */ prev = NULL; node = node->parent->children; new_location = 0; tmp_iter.user_data = node; if (tree_store->order == GTK_SORT_DESCENDING) cmp_a = (* func) (GTK_TREE_MODEL (tree_store), &tmp_iter, iter, data); else cmp_a = (* func) (GTK_TREE_MODEL (tree_store), iter, &tmp_iter, data); while ((node->next) && (cmp_a > 0)) { prev = node; node = node->next; new_location++; tmp_iter.user_data = node; if (tree_store->order == GTK_SORT_DESCENDING) cmp_a = (* func) (GTK_TREE_MODEL (tree_store), &tmp_iter, iter, data); else cmp_a = (* func) (GTK_TREE_MODEL (tree_store), iter, &tmp_iter, data); } if ((!node->next) && (cmp_a > 0)) { new_location++; node->next = G_NODE (iter->user_data); node->next->prev = node; } else if (prev) { prev->next = G_NODE (iter->user_data); prev->next->prev = prev; G_NODE (iter->user_data)->next = node; G_NODE (iter->user_data)->next->prev = G_NODE (iter->user_data); } else { G_NODE (iter->user_data)->next = G_NODE (iter->user_data)->parent->children; G_NODE (iter->user_data)->next->prev = G_NODE (iter->user_data); G_NODE (iter->user_data)->parent->children = G_NODE (iter->user_data); } if (!emit_signal) return; /* Emit the reordered signal. */ length = g_node_n_children (node->parent); new_order = g_new (int, length); if (old_location < new_location) for (i = 0; i < length; i++) { if (i < old_location || i > new_location) new_order[i] = i; else if (i >= old_location && i < new_location) new_order[i] = i + 1; else if (i == new_location) new_order[i] = old_location; } else for (i = 0; i < length; i++) { if (i < new_location || i > old_location) new_order[i] = i; else if (i > new_location && i <= old_location) new_order[i] = i - 1; else if (i == new_location) new_order[i] = old_location; } tmp_iter.user_data = node->parent; tmp_path = foo_tree_store_get_path (GTK_TREE_MODEL (tree_store), &tmp_iter); gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store), tmp_path, &tmp_iter, new_order); gtk_tree_path_free (tmp_path); g_free (new_order); } static gboolean foo_tree_store_get_sort_column_id (GtkTreeSortable *sortable, gint *sort_column_id, GtkSortType *order) { FooTreeStore *tree_store = (FooTreeStore *) sortable; if (sort_column_id) * sort_column_id = tree_store->sort_column_id; if (order) * order = tree_store->order; if (tree_store->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID || tree_store->sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID) return FALSE; return TRUE; } static void foo_tree_store_set_sort_column_id (GtkTreeSortable *sortable, gint sort_column_id, GtkSortType order) { FooTreeStore *tree_store = (FooTreeStore *) sortable; if ((tree_store->sort_column_id == sort_column_id) && (tree_store->order == order)) return; if (sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID) { if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID) { GtkTreeDataSortHeader *header = NULL; header = _foo_tree_data_list_get_header (tree_store->sort_list, sort_column_id); /* We want to make sure that we have a function */ g_return_if_fail (header != NULL); g_return_if_fail (header->func != NULL); } else { g_return_if_fail (tree_store->default_sort_func != NULL); } } tree_store->sort_column_id = sort_column_id; tree_store->order = order; gtk_tree_sortable_sort_column_changed (sortable); foo_tree_store_sort (tree_store); } static void foo_tree_store_set_sort_func (GtkTreeSortable *sortable, gint sort_column_id, GtkTreeIterCompareFunc func, gpointer data, GDestroyNotify destroy) { FooTreeStore *tree_store = (FooTreeStore *) sortable; tree_store->sort_list = _foo_tree_data_list_set_header (tree_store->sort_list, sort_column_id, func, data, destroy); if (tree_store->sort_column_id == sort_column_id) foo_tree_store_sort (tree_store); } static void foo_tree_store_set_default_sort_func (GtkTreeSortable *sortable, GtkTreeIterCompareFunc func, gpointer data, GDestroyNotify destroy) { FooTreeStore *tree_store = (FooTreeStore *) sortable; if (tree_store->default_sort_destroy) { GDestroyNotify d = tree_store->default_sort_destroy; tree_store->default_sort_destroy = NULL; d (tree_store->default_sort_data); } tree_store->default_sort_func = func; tree_store->default_sort_data = data; tree_store->default_sort_destroy = destroy; if (tree_store->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID) foo_tree_store_sort (tree_store); } static gboolean foo_tree_store_has_default_sort_func (GtkTreeSortable *sortable) { FooTreeStore *tree_store = (FooTreeStore *) sortable; return (tree_store->default_sort_func != NULL); } static void validate_gnode (GNode* node) { GNode *iter; iter = node->children; while (iter != NULL) { g_assert (iter->parent == node); if (iter->prev) g_assert (iter->prev->next == iter); validate_gnode (iter); iter = iter->next; } } /* GtkBuildable custom tag implementation * * * * * */ typedef struct { GtkBuilder *builder; GObject *object; GSList *items; } GSListSubParserData; static void tree_model_start_element (GMarkupParseContext *context, const gchar *element_name, const gchar **names, const gchar **values, gpointer user_data, GError **error) { guint i; GSListSubParserData *data = (GSListSubParserData*)user_data; for (i = 0; names[i]; i++) { if (strcmp (names[i], "type") == 0) data->items = g_slist_prepend (data->items, g_strdup (values[i])); } } static void tree_model_end_element (GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error) { GSListSubParserData *data = (GSListSubParserData*)user_data; g_assert(data->builder); if (strcmp (element_name, "columns") == 0) { GSList *l; GType *types; int i; GType type; data = (GSListSubParserData*)user_data; data->items = g_slist_reverse (data->items); types = g_new0 (GType, g_slist_length (data->items)); for (l = data->items, i = 0; l; l = l->next, i++) { type = gtk_builder_get_type_from_name (data->builder, l->data); if (type == G_TYPE_INVALID) { g_warning ("Unknown type %s specified in treemodel %s", (const gchar*)l->data, gtk_buildable_get_name (GTK_BUILDABLE (data->object))); continue; } types[i] = type; g_free (l->data); } foo_tree_store_set_column_types (FOO_TREE_STORE (data->object), i, types); g_free (types); } else if (strcmp (element_name, "column") == 0) ; } static const GMarkupParser tree_model_parser = { tree_model_start_element, tree_model_end_element }; static gboolean foo_tree_store_buildable_custom_tag_start (GtkBuildable *buildable, GtkBuilder *builder, GObject *child, const gchar *tagname, GMarkupParser *parser, gpointer *data) { GSListSubParserData *parser_data; if (child) return FALSE; if (strcmp (tagname, "columns") == 0) { parser_data = g_slice_new0 (GSListSubParserData); parser_data->builder = builder; parser_data->items = NULL; parser_data->object = G_OBJECT (buildable); *parser = tree_model_parser; *data = parser_data; return TRUE; } return FALSE; } static void foo_tree_store_buildable_custom_finished (GtkBuildable *buildable, GtkBuilder *builder, GObject *child, const gchar *tagname, gpointer user_data) { GSListSubParserData *data; if (strcmp (tagname, "columns")) return; data = (GSListSubParserData*)user_data; g_slist_free (data->items); g_slice_free (GSListSubParserData, data); } sysprof-1.2.0/watch.h0000644000175000017500000000306612021176713011424 00000000000000/* - Library for asynchronous communication * Copyright (C) 2002 Søren Sandmann (sandmann@daimi.au.dk) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include /* * Watching file descriptors */ typedef void (* WatchCallback) (gpointer data); void fd_add_watch (gint fd, gpointer data); void fd_set_read_callback (gint fd, WatchCallback read_cb); void fd_set_write_callback (gint fd, WatchCallback write_cb); void fd_set_hangup_callback (gint fd, WatchCallback hangup_cb); void fd_set_error_callback (gint fd, WatchCallback error_cb); void fd_set_priority_callback (gint fd, WatchCallback priority_cb); void fd_remove_watch (gint fd); gboolean fd_is_watched (gint fd); sysprof-1.2.0/sfile.h0000644000175000017500000001300112021176713011406 00000000000000/* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, Red Hat, Inc. * Copyright 2004, 2005, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "sformat.h" typedef struct SFileInput SFileInput; typedef struct SFileOutput SFileOutput; #if 0 Serializer *serializer_new (const char *version); void serializer_set_format (Serializer *serializer, SerializerFormat *format); SerializerFormat *serializer_make_list (Serializer *serializer, const char *name, SerializerFormat *contents); SerializerFormat *serializer_make_record (Serializer *serializer, const char *name, SerializerFormat *contents1, ...); SerializerFormat *serializer_make_integer (Serializer *serialiser, const char *name); SerializerFormat *serializer_make_pointer (Serializer *serialiser, const char *name, SerializerFormat *target_type); #endif /* A possibly better API/naming scheme * * Serializer *serializer_new (SerializerFormat *format); * * SerializerReadContext *serializer_begin_read_filename (serializer *serialize, * const char *filename, * GError *err); * serializer_get_blah (SerializerReadContext *); * void serialzier_end_read (...); * * SerializerWritecontext *...; * serializer_begin_write (context); * serializer_write_int (); * serializer_end_write (..., GError **err); * * * For formats consider: * * Format *format_new (void); * void format_free (void); * Content *format_create_record (Format *format, Content *c1, ...); * Content *format_create_list (Format *format, Content *t); * Content *format_create_pointer (Format *format, Content *pointer_type); * * void format_set_record (Format *f, Content *r); * Content *new_record (Content *c1, ...); * * List *format_new_list (Format *f * * * Consider adding optional elements: * * sformat_new_optional (gpointer content) * * enums, optionals, selections, empties * * * Other things: * * "selections" - when several different types are possible - would need lambda transitions in and out * * ability to allow 'ignored' elements that are simply skipped at parse time. This could become important * for future-proofing files. * * unions maybe? * * * * *============================================== * Also think about versioning - apps will want to be able to read and write * different versions of the format, and they want to be able to sniff the * format + version * * The version should be part of the format. There should be a * const char *sfile_sniff (const filename); * that will return NULL (+ error) if the file can't be parsed * */ /* - Describing Types - */ /* - Reading - */ SFileInput * sfile_load (const char *filename, SFormat *format, GError **err); void sfile_begin_get_record (SFileInput *file, const char *name); int sfile_begin_get_list (SFileInput *file, const char *name); void sfile_get_pointer (SFileInput *file, const char *name, gpointer *pointer); void sfile_get_integer (SFileInput *file, const char *name, gint32 *integer); void sfile_get_string (SFileInput *file, const char *name, char **string); void sfile_end_get (SFileInput *file, const char *name, gpointer object); void sfile_input_free (SFileInput *file); #if 0 /* incremental loading (worth considering at least) */ SFileLoader *sfile_loader_new (SFormat *format); void sfile_loader_add_text (SFileLoader *loader, const char *text, int len); SFile * sfile_loader_finish (SFileLoader *loader, GError **err); void sfile_loader_free (SFileLoader *loader); #endif /* - Writing - */ /* FIXME - not10: see if we can't get rid of the names. It * should be possible to pass NULL to state_transition_check() * and have it interprete that as "whatever". We would need * a way to get the name back then, though. */ SFileOutput * sfile_output_new (SFormat *format); void sfile_begin_add_record (SFileOutput *file, const char *name); void sfile_begin_add_list (SFileOutput *file, const char *name); void sfile_end_add (SFileOutput *file, const char *name, gpointer object); void sfile_add_string (SFileOutput *file, const char *name, const char *string); void sfile_add_integer (SFileOutput *file, const char *name, int integer); void sfile_add_pointer (SFileOutput *file, const char *name, gpointer pointer); gboolean sfile_output_save (SFileOutput *sfile, const char *filename, GError **err); void sfile_output_free (SFileOutput *sfile); sysprof-1.2.0/aclocal.m40000644000175000017500000013016512022706422012003 00000000000000# generated automatically by aclocal 1.11.3 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, # Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],, [m4_warning([this file was generated for autoconf 2.68. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 1 (pkg-config-0.24) # # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) # only at the first occurence in configure.ac, so if the first place # it's called might be skipped (such as if it is within an "if", you # have to call PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT]) ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .]) ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])# PKG_CHECK_MODULES # Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 Free Software # Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 1 # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.11' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.11.3], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.11.3])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 1 # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 9 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, # 2010, 2011 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 12 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], UPC, [depcc="$UPC" am_compiler_list=], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. #serial 5 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2008, 2009 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 16 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.62])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES(OBJC)], [define([AC_PROG_OBJC], defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl ]) _AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl dnl The `parallel-tests' driver may need to know about EXEEXT, so add the dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005, 2008, 2011 Free Software Foundation, # Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 1 # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008, # 2011 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. # Default is to disable them, unless `enable' is passed literally. # For symmetry, `disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), [enable], [m4_define([am_maintainer_other], [disable])], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful (and sometimes confusing) to the casual installer], [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST([MAINT])dnl ] ) AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from `make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 6 # AM_PROG_CC_C_O # -------------- # Like AC_PROG_CC_C_O, but changed for automake. AC_DEFUN([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC_C_O])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi dnl Make sure AC_PROG_CC is never called again, or it will override our dnl setting of CC. m4_define([AC_PROG_CC], [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 6 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005, 2006, 2011 Free Software Foundation, # Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 1 # AM_PROG_MKDIR_P # --------------- # Check for `mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2008, 2010 Free Software # Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; esac # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # Copyright (C) 2009, 2011 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # (`yes' being less verbose, `no' or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [ --enable-silent-rules less verbose build output (undo: `make V=1') --disable-silent-rules verbose build output (undo: `make V=0')]) case $enable_silent_rules in yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few `make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using `$V' instead of `$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 1 # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006, 2008, 2010 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005, 2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of `v7', `ustar', or `pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR sysprof-1.2.0/stackstash.c0000644000175000017500000001672412021200736012457 00000000000000/* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, Red Hat, Inc. * Copyright 2004, 2005, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "stackstash.h" struct StackStash { int ref_count; StackNode * root; GHashTable * nodes_by_data; GDestroyNotify destroy; StackNode * cached_nodes; GPtrArray * blocks; }; static void decorate_node (StackNode *node, StackStash *stash) { StackNode *n; if (!node) return; decorate_node (node->siblings, stash); decorate_node (node->children, stash); node->next = g_hash_table_lookup (stash->nodes_by_data, &node->data); g_hash_table_insert (stash->nodes_by_data, &node->data, node); /* FIXME: This could be done more efficiently * by keeping track of the ancestors we have seen. */ node->toplevel = TRUE; for (n = node->parent; n != NULL; n = n->parent) { if (n->data == node->data) { node->toplevel = FALSE; break; } } } static unsigned int address_hash (gconstpointer key) { const uint64_t *addr = key; return *addr; } static gboolean address_equal (gconstpointer key1, gconstpointer key2) { const uint64_t *addr1 = key1; const uint64_t *addr2 = key2; return *addr1 == *addr2; } static void stack_stash_decorate (StackStash *stash) { if (stash->nodes_by_data) return; stash->nodes_by_data = g_hash_table_new (address_hash, address_equal); decorate_node (stash->root, stash); } static void free_key (gpointer key, gpointer value, gpointer data) { GDestroyNotify destroy = data; uint64_t u64 = *(uint64_t *)key; destroy (U64_TO_POINTER (u64)); } static void stack_stash_undecorate (StackStash *stash) { if (stash->nodes_by_data) { if (stash->destroy) { g_hash_table_foreach ( stash->nodes_by_data, free_key, stash->destroy); } g_hash_table_destroy (stash->nodes_by_data); stash->nodes_by_data = NULL; } } static GHashTable * get_nodes_by_data (StackStash *stash) { if (!stash->nodes_by_data) stack_stash_decorate (stash); return stash->nodes_by_data; } StackNode * stack_node_new (StackStash *stash) { StackNode *node; if (!stash->cached_nodes) { #define BLOCK_SIZE 32768 #define N_NODES (BLOCK_SIZE / sizeof (StackNode)) StackNode *block = g_malloc (BLOCK_SIZE); int i; for (i = 0; i < N_NODES; ++i) { block[i].next = stash->cached_nodes; stash->cached_nodes = &(block[i]); } g_ptr_array_add (stash->blocks, block); } node = stash->cached_nodes; stash->cached_nodes = node->next; node->siblings = NULL; node->children = NULL; node->data = 0; node->parent = NULL; node->size = 0; node->next = NULL; node->total = 0; return node; } /* "destroy", if non-NULL, is called once on every address */ static StackStash * create_stack_stash (GDestroyNotify destroy) { StackStash *stash = g_new (StackStash, 1); stash->root = NULL; stash->nodes_by_data = NULL; stash->ref_count = 1; stash->destroy = destroy; stash->cached_nodes = NULL; stash->blocks = g_ptr_array_new (); return stash; } /* Stach */ StackStash * stack_stash_new (GDestroyNotify destroy) { return create_stack_stash (destroy); } static void stack_stash_free (StackStash *stash) { int i; stack_stash_undecorate (stash); for (i = 0; i < stash->blocks->len; ++i) g_free (stash->blocks->pdata[i]); g_ptr_array_free (stash->blocks, TRUE); g_free (stash); } StackNode * stack_stash_add_trace (StackStash *stash, uint64_t *addrs, int n_addrs, int size) { StackNode **location = &(stash->root); StackNode *parent = NULL; int i; if (!n_addrs) return NULL; if (stash->nodes_by_data) stack_stash_undecorate (stash); for (i = n_addrs - 1; i >= 0; --i) { StackNode *match = NULL; StackNode *prev; /* FIXME: On x86-64 we don't get proper stacktraces which means * each node can have tons of children. That makes this loop * here show up on profiles. * * Not sure what can be done about it aside from actually fixing * x86-64 to get stacktraces. */ prev = NULL; for (match = *location; match; prev = match, match = match->siblings) { if (match->data == addrs[i]) { if (prev) { /* move to front */ prev->siblings = match->siblings; match->siblings = *location; *location = match; } break; } } if (!match) { match = stack_node_new (stash); match->data = addrs[i]; match->siblings = *location; match->parent = parent; *location = match; } match->total += size; location = &(match->children); parent = match; } parent->size += size; return parent; } static void do_callback (StackNode *node, StackLink *trace, StackFunction func, gpointer data) { StackLink link; if (trace) trace->prev = &link; link.next = trace; link.prev = NULL; while (node) { link.data = node->data; if (node->size) func (&link, node->size, data); do_callback (node->children, &link, func, data); node = node->siblings; } if (trace) trace->prev = NULL; } void stack_stash_foreach (StackStash *stash, StackFunction stack_func, gpointer data) { do_callback (stash->root, NULL, stack_func, data); } void stack_node_foreach_trace (StackNode *node, StackFunction func, gpointer data) { StackLink link; link.next = NULL; link.data = node->data; link.prev = NULL; if (node->size) func (&link, node->size, data); do_callback (node->children, &link, func, data); } void stack_stash_unref (StackStash *stash) { stash->ref_count--; if (stash->ref_count == 0) stack_stash_free (stash); } StackStash * stack_stash_ref (StackStash *stash) { stash->ref_count++; return stash; } StackNode * stack_stash_find_node (StackStash *stash, gpointer data) { uint64_t u64 = POINTER_TO_U64 (data); g_return_val_if_fail (stash != NULL, NULL); return g_hash_table_lookup (get_nodes_by_data (stash), &u64); } typedef struct { StackNodeFunc func; gpointer data; } Info; static void do_foreach (gpointer key, gpointer value, gpointer data) { Info *info = data; info->func (value, info->data); } void stack_stash_foreach_by_address (StackStash *stash, StackNodeFunc func, gpointer data) { Info info; info.func = func; info.data = data; g_hash_table_foreach (get_nodes_by_data (stash), do_foreach, &info); } StackNode * stack_stash_get_root (StackStash *stash) { return stash->root; } void stack_stash_set_root (StackStash *stash, StackNode *root) { g_return_if_fail (stash->root == NULL); stash->root = root; } sysprof-1.2.0/elfparser.c0000644000175000017500000005035512021176713012277 00000000000000/* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2006, 2007, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "elfparser.h" typedef struct Section Section; struct ElfSym { gulong table; gulong offset; gulong address; }; struct Section { const gchar * name; gsize offset; gsize size; gboolean allocated; gulong load_address; guint type; }; struct ElfParser { gboolean is_64; const guchar * data; gsize length; int n_sections; Section ** sections; int n_symbols; ElfSym * symbols; gsize sym_strings; GMappedFile * file; char * filename; gboolean checked_build_id; char * build_id; const Section * text_section; }; /* FIXME: All of these should in principle do endian swapping, * but sysprof never has to deal with binaries of a different * endianness than sysprof itself */ #define GET_FIELD(parser, offset, struct_name, idx, field_name) \ (((parser))->is_64? \ ((Elf64_ ## struct_name *)(((parser)->data + offset)) + (idx))->field_name : \ ((Elf32_ ## struct_name *)(((parser)->data + offset)) + (idx))->field_name) #define GET_UINT32(parser, offset) \ *((uint32_t *)(parser->data + offset)) \ #define GET_SIZE(parser, struct_name) \ (((parser)->is_64? \ sizeof (Elf64_ ## struct_name) : \ sizeof (Elf32_ ## struct_name))) #define MAKE_ELF_UINT_ACCESSOR(field_name) \ static uint64_t field_name (ElfParser *parser) \ { \ return GET_FIELD (parser, 0, Ehdr, 0, field_name); \ } MAKE_ELF_UINT_ACCESSOR (e_shoff) MAKE_ELF_UINT_ACCESSOR (e_shnum) MAKE_ELF_UINT_ACCESSOR (e_shstrndx) #define MAKE_SECTION_HEADER_ACCESSOR(field_name) \ static uint64_t field_name (ElfParser *parser, int nth_section) \ { \ gsize offset = e_shoff (parser); \ \ return GET_FIELD (parser, offset, Shdr, nth_section, field_name); \ } MAKE_SECTION_HEADER_ACCESSOR (sh_name); MAKE_SECTION_HEADER_ACCESSOR (sh_type); MAKE_SECTION_HEADER_ACCESSOR (sh_flags); MAKE_SECTION_HEADER_ACCESSOR (sh_addr); MAKE_SECTION_HEADER_ACCESSOR (sh_offset); MAKE_SECTION_HEADER_ACCESSOR (sh_size); #define MAKE_SYMBOL_ACCESSOR(field_name) \ static uint64_t field_name (ElfParser *parser, gulong offset, gulong nth) \ { \ return GET_FIELD (parser, offset, Sym, nth, field_name); \ } MAKE_SYMBOL_ACCESSOR(st_name); MAKE_SYMBOL_ACCESSOR(st_info); MAKE_SYMBOL_ACCESSOR(st_value); MAKE_SYMBOL_ACCESSOR(st_size); MAKE_SYMBOL_ACCESSOR(st_shndx); static void section_free (Section *section) { g_free (section); } static const Section * find_section (ElfParser *parser, const char *name, guint type) { int i; for (i = 0; i < parser->n_sections; ++i) { Section *section = parser->sections[i]; if (strcmp (section->name, name) == 0 && section->type == type) return section; } return NULL; } static gboolean parse_elf_signature (const guchar *data, gsize length, gboolean *is_64, gboolean *is_be) { /* FIXME: this function should be able to return an error */ if (length < EI_NIDENT) { /* FIXME set error */ return FALSE; } if (data[EI_CLASS] != ELFCLASS32 && data[EI_CLASS] != ELFCLASS64) { /* FIXME set error */ return FALSE; } if (data[EI_DATA] != ELFDATA2LSB && data[EI_DATA] != ELFDATA2MSB) { /* FIXME set error */ return FALSE; } if (is_64) *is_64 = (data[EI_CLASS] == ELFCLASS64); if (is_be) *is_be = (data[EI_DATA] == ELFDATA2MSB); return TRUE; } ElfParser * elf_parser_new_from_data (const guchar *data, gsize length) { ElfParser *parser; gboolean is_64, is_big_endian; int section_names_idx; const guchar *section_names; gsize section_headers; int i; if (!parse_elf_signature (data, length, &is_64, &is_big_endian)) { /* FIXME: set error */ return NULL; } parser = g_new0 (ElfParser, 1); parser->is_64 = is_64; parser->data = data; parser->length = length; #if 0 g_print (" new parser : %p\n", parser); #endif /* Read ELF header */ parser->n_sections = e_shnum (parser); section_names_idx = e_shstrndx (parser); section_headers = e_shoff (parser); /* Read section headers */ parser->sections = g_new0 (Section *, parser->n_sections); section_names = parser->data + sh_offset (parser, section_names_idx); for (i = 0; i < parser->n_sections; ++i) { Section *section = g_new (Section, 1); section->name = (char *)(section_names + sh_name (parser, i)); section->size = sh_size (parser, i); section->offset = sh_offset (parser, i); section->allocated = !!(sh_flags (parser, i) & SHF_ALLOC); if (section->allocated) section->load_address = sh_addr (parser, i); else section->load_address = 0; section->type = sh_type (parser, i); parser->sections[i] = section; } /* Cache the text section */ parser->text_section = find_section (parser, ".text", SHT_PROGBITS); if (!parser->text_section) parser->text_section = find_section (parser, ".text", SHT_NOBITS); parser->filename = NULL; parser->build_id = NULL; return parser; } ElfParser * elf_parser_new (const char *filename, GError **err) { const guchar *data; gsize length; ElfParser *parser; GMappedFile *file = g_mapped_file_new (filename, FALSE, NULL); if (!file) return NULL; #if 0 g_print ("elf parser new : %s\n", filename); #endif data = (guchar *)g_mapped_file_get_contents (file); length = g_mapped_file_get_length (file); #if 0 g_print ("data %p: for %s\n", data, filename); #endif parser = elf_parser_new_from_data (data, length); #if 0 g_print ("Parser for %s: %p\n", filename, parser); #endif if (!parser) { g_mapped_file_free (file); return NULL; } parser->filename = g_strdup (filename); parser->file = file; #if 0 g_print ("Elf file: %s (debug: %s)\n", filename, elf_parser_get_debug_link (parser, NULL)); if (!parser->symbols) g_print ("at this point %s has no symbols\n", filename); #endif return parser; } guint32 elf_parser_get_crc32 (ElfParser *parser) { static const unsigned long crc32_table[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; const guchar *data; gsize length; gulong crc; gsize i; data = parser->data; length = parser->length; crc = 0xffffffff; madvise ((char *)data, length, MADV_SEQUENTIAL); for (i = 0; i < length; ++i) crc = crc32_table[(crc ^ data[i]) & 0xff] ^ (crc >> 8); /* We just read the entire file into memory, but we only really * need the symbol table, so swap the whole thing out. * * We could be more exact here, but it's only a few minor * pagefaults. */ if (parser->file) madvise ((char *)data, length, MADV_DONTNEED); return ~crc & 0xffffffff; } void elf_parser_free (ElfParser *parser) { int i; for (i = 0; i < parser->n_sections; ++i) section_free (parser->sections[i]); g_free (parser->sections); if (parser->file) g_mapped_file_free (parser->file); g_free (parser->symbols); if (parser->filename) g_free (parser->filename); if (parser->build_id) g_free (parser->build_id); g_free (parser); } extern char *sysprof_cplus_demangle (const char *name, int options); char * elf_demangle (const char *name) { #define DMGL_PARAMS (1 << 0) /* Include function args */ #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ char *demangled = sysprof_cplus_demangle (name, DMGL_PARAMS | DMGL_ANSI); if (demangled) return demangled; else return g_strdup (name); } /* * Looking up symbols */ static int compare_sym (const void *a, const void *b) { const ElfSym *sym_a = a; const ElfSym *sym_b = b; if (sym_a->address < sym_b->address) return -1; else if (sym_a->address == sym_b->address) return 0; else return 1; } #if 0 static void dump_symbols (ElfParser *parser, ElfSym *syms, guint n_syms) { int i; for (i = 0; i < n_syms; ++i) { ElfSym *s = &(syms[i]); g_print (" %s: %lx\n", elf_parser_get_sym_name (parser, s), s->address); } } #endif static void read_table (ElfParser *parser, const Section *sym_table, const Section *str_table) { int sym_size = GET_SIZE (parser, Sym); int i, n_symbols; #if 0 g_print ("elf: Reading table for %s\n", parser->filename? parser->filename : ""); #endif parser->n_symbols = sym_table->size / sym_size; parser->symbols = g_new (ElfSym, parser->n_symbols); #if 0 g_print ("sym table offset: %d\n", sym_table->offset); #endif n_symbols = 0; #if 0 g_print ("n syms: %d\n", parser->n_symbols); #endif for (i = 0; i < parser->n_symbols; ++i) { guint info; gulong addr; gulong shndx; info = st_info (parser, sym_table->offset, i); addr = st_value (parser, sym_table->offset, i); shndx = st_shndx (parser, sym_table->offset, i); #if 0 g_print ("read symbol: %s (section: %d)\n", get_string_indirct (parser->parser, parser->sym_format, "st_name", str_table->offset), shndx); #endif if (addr != 0 && shndx < parser->n_sections && parser->sections[shndx] == parser->text_section && (info & 0xf) == STT_FUNC && ((info >> 4) == STB_GLOBAL || (info >> 4) == STB_LOCAL || (info >> 4) == STB_WEAK)) { parser->symbols[n_symbols].address = addr; parser->symbols[n_symbols].table = sym_table->offset; parser->symbols[n_symbols].offset = i; n_symbols++; #if 0 g_print (" symbol: %s: %lx\n", get_string_indirect (parser->parser, parser->sym_format, "st_name", str_table->offset), addr - parser->text_section->load_address); g_print (" sym %d in %p (info: %d:%d) (func:global %d:%d)\n", addr, parser, info & 0xf, info >> 4, STT_FUNC, STB_GLOBAL); #endif } else if (addr != 0) { #if 0 g_print (" rejecting %d in %p (info: %d:%d) (func:global %d:%d)\n", addr, parser, info & 0xf, info >> 4, STT_FUNC, STB_GLOBAL); #endif } } parser->sym_strings = str_table->offset; parser->n_symbols = n_symbols; /* Allocate space for at least one symbol, so that parser->symbols will be * non-NULL. If it ends up being NULL, we will be parsing the file over and * over. */ parser->symbols = g_renew (ElfSym, parser->symbols, parser->n_symbols + 1); qsort (parser->symbols, parser->n_symbols, sizeof (ElfSym), compare_sym); } static void read_symbols (ElfParser *parser) { const Section *symtab = find_section (parser, ".symtab", SHT_SYMTAB); const Section *strtab = find_section (parser, ".strtab", SHT_STRTAB); const Section *dynsym = find_section (parser, ".dynsym", SHT_DYNSYM); const Section *dynstr = find_section (parser, ".dynstr", SHT_STRTAB); if (symtab && strtab) { #if 0 g_print ("reading symbol table of %s\n", parser->filename); #endif read_table (parser, symtab, strtab); } else if (dynsym && dynstr) { #if 0 g_print ("reading dynamic symbol table of %s\n", parser->filename); #endif read_table (parser, dynsym, dynstr); } else { /* To make sure parser->symbols is non-NULL */ parser->n_symbols = 0; parser->symbols = g_new (ElfSym, 1); } } static ElfSym * do_lookup (ElfSym *symbols, gulong address, int first, int last) { if (address >= symbols[last].address) { return &(symbols[last]); } else if (last - first < 3) { while (last >= first) { if (address >= symbols[last].address) return &(symbols[last]); last--; } return NULL; } else { int mid = (first + last) / 2; if (symbols[mid].address > address) return do_lookup (symbols, address, first, mid); else return do_lookup (symbols, address, mid, last); } } /* Address should be given in 'offset into text segment' */ const ElfSym * elf_parser_lookup_symbol (ElfParser *parser, gulong address) { const ElfSym *result; if (!parser->symbols) { #if 0 g_print ("reading symbols at %p\n", parser); #endif read_symbols (parser); } if (parser->n_symbols == 0) return NULL; if (!parser->text_section) return NULL; address += parser->text_section->load_address; #if 0 g_print ("elf: the address we are looking up is %p\n", address); #endif result = do_lookup (parser->symbols, address, 0, parser->n_symbols - 1); #if 0 if (result) { g_print (" elf: found %s at %lx\n", elf_parser_get_sym_name (parser, result), result->address); } else { g_print ("elf: not found\n"); } #endif if (result) { gulong size = st_size (parser, result->table, result->offset); if (size > 0 && result->address + size <= address) { #if 0 g_print (" elf: ends at %lx, so rejecting\n", result->address + size); #endif result = NULL; } } if (result) { /* Reject the symbols if the address is outside the text section */ if (address > parser->text_section->load_address + parser->text_section->size) result = NULL; } return result; } gulong elf_parser_get_text_offset (ElfParser *parser) { g_return_val_if_fail (parser != NULL, (gulong)-1); if (!parser->text_section) return (gulong)-1; return parser->text_section->offset; } static gchar * make_hex_string (const guchar *data, int n_bytes) { static const char hex_digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; GString *string = g_string_new (NULL); int i; for (i = 0; i < n_bytes; ++i) { char c = data[i]; g_string_append_c (string, hex_digits[(c & 0xf0) >> 4]); g_string_append_c (string, hex_digits[(c & 0x0f)]); } return g_string_free (string, FALSE); } const gchar * elf_parser_get_build_id (ElfParser *parser) { if (!parser->checked_build_id) { const Section *build_id = find_section (parser, ".note.gnu.build-id", SHT_NOTE); guint64 name_size; guint64 desc_size; guint64 type; const char *name; guint64 offset; parser->checked_build_id = TRUE; if (!build_id) return NULL; offset = build_id->offset; name_size = GET_FIELD (parser, offset, Nhdr, 0, n_namesz); desc_size = GET_FIELD (parser, offset, Nhdr, 0, n_descsz); type = GET_FIELD (parser, offset, Nhdr, 0, n_type); offset += GET_SIZE (parser, Nhdr); name = (char *)(parser->data + offset); if (strncmp (name, ELF_NOTE_GNU, name_size) != 0 || type != NT_GNU_BUILD_ID) return NULL; offset += strlen (name); offset = (offset + 3) & (~0x3); parser->build_id = make_hex_string (parser->data + offset, desc_size); } return parser->build_id; } const char * elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32) { guint64 offset; const Section *debug_link = find_section (parser, ".gnu_debuglink", SHT_PROGBITS); const gchar *result; if (!debug_link) return NULL; offset = debug_link->offset; result = (char *)(parser->data + offset); if (crc32) { int len = strlen (result) + 1; offset = (offset + len + 3) & ~0x3; *crc32 = GET_UINT32 (parser, offset); } return result; } const guchar * get_section (ElfParser *parser, const char *name) { const Section *section = find_section (parser, name, SHT_PROGBITS); if (section) return parser->data + section->offset; else return NULL; } const guchar * elf_parser_get_eh_frame (ElfParser *parser) { return get_section (parser, ".eh_frame"); } const guchar * elf_parser_get_debug_frame (ElfParser *parser) { return get_section (parser, ".debug_frame"); } const char * elf_parser_get_sym_name (ElfParser *parser, const ElfSym *sym) { g_return_val_if_fail (parser != NULL, NULL); return (char *)(parser->data + parser->sym_strings + st_name (parser, sym->table, sym->offset)); } gboolean elf_parser_owns_symbol (ElfParser *parser, const ElfSym *sym) { ElfSym *first, *last; if (!parser->n_symbols) return FALSE; first = parser->symbols; last = parser->symbols + parser->n_symbols - 1; return first <= sym && sym <= last; } gulong elf_parser_get_sym_address (ElfParser *parser, const ElfSym *sym) { return sym->address - parser->text_section->load_address; } /* * Utility functions */ sysprof-1.2.0/profile.h0000644000175000017500000000467512021176713011765 00000000000000/* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, Red Hat, Inc. * Copyright 2004, 2005, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PROFILE_H #define PROFILE_H #include #include "stackstash.h" typedef struct Profile Profile; typedef struct ProfileObject ProfileObject; typedef struct ProfileDescendant ProfileDescendant; typedef struct ProfileCaller ProfileCaller; struct ProfileObject { char * name; /* identifies this object uniquely * (the pointer itself, not the * string) */ guint total; /* sum of all toplevel totals */ guint self; /* sum of all selfs */ }; struct ProfileDescendant { char * name; guint self; guint cumulative; ProfileDescendant * parent; ProfileDescendant * siblings; ProfileDescendant * children; }; struct ProfileCaller { char * name; guint total; guint self; ProfileCaller * next; }; Profile * profile_new (StackStash *stash); void profile_free (Profile *profile); gint profile_get_size (Profile *profile); GList * profile_get_objects (Profile *profile); ProfileDescendant *profile_create_descendants (Profile *prf, char *object); ProfileCaller * profile_list_callers (Profile *profile, char *object); void profile_caller_free (ProfileCaller *caller); void profile_descendant_free (ProfileDescendant *descendant); gboolean profile_save (Profile *profile, const char *file_name, GError **err); Profile * profile_load (const char *filename, GError **err); #endif /* PROFILE_H */ sysprof-1.2.0/INSTALL0000644000175000017500000003660012021176741011177 00000000000000Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. sysprof-1.2.0/util.h0000644000175000017500000000204312021176713011265 00000000000000#ifndef UTIL_H #define UTIL_H #define FMT64 "%"G_GUINT64_FORMAT #if defined(__i386__) #define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") #define cpu_relax() asm volatile("rep; nop" ::: "memory"); #endif #if defined(__x86_64__) #define rmb() asm volatile("lfence" ::: "memory") #define cpu_relax() asm volatile("rep; nop" ::: "memory"); #endif #ifdef __powerpc__ #define rmb() asm volatile ("sync" ::: "memory") #define cpu_relax() asm volatile ("" ::: "memory"); #endif #ifdef __s390__ #define rmb() asm volatile("bcr 15,0" ::: "memory") #define cpu_relax() asm volatile("" ::: "memory"); #endif #ifdef __sh__ #if defined(__SH4A__) || defined(__SH5__) # define rmb() asm volatile("synco" ::: "memory") #else # define rmb() asm volatile("" ::: "memory") #endif #define cpu_relax() asm volatile("" ::: "memory") #endif #ifdef __hppa__ #define rmb() asm volatile("" ::: "memory") #define cpu_relax() asm volatile("" ::: "memory"); #endif #endif sysprof-1.2.0/sysprof.glade0000644000175000017500000010362512021176713012652 00000000000000 System Profiler GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False 700 500 True False True False False GDK_WINDOW_TYPE_HINT_NORMAL GDK_GRAVITY_NORTH_WEST True False True False 0 True GTK_PACK_DIRECTION_LTR GTK_PACK_DIRECTION_LTR True _Profiler True True _Start True True gtk-media-play 1 0.5 0.5 0 0 True _Profile True True gtk-justify-left 1 0.5 0.5 0 0 True _Reset True True gtk-clear 1 0.5 0.5 0 0 True True _Open... True True gtk-open 1 0.5 0.5 0 0 True Save _As... True True gtk-save-as 1 0.5 0.5 0 0 True True _Quit True True gtk-quit 1 0.5 0.5 0 0 True _View True True _Screenshot Window True False True _Help True True _About True True gtk-about 1 0.5 0.5 0 0 0 False False True 0.5 0.5 1 1 0 3 3 3 True 0 False True True False 0 True GTK_ORIENTATION_HORIZONTAL True True True S_tart True gtk-media-play True True True False False True True _Profile True gtk-justify-left True True True False start_button False True True _Reset True gtk-clear True True False False True True True True False True True True True False False True gtk-save-as True True True False True True dummy True True True False False start_button False True 3 True True True GTK_ORIENTATION_HORIZONTAL GTK_TOOLBAR_BOTH_HORIZ True False True True True False True False False GTK_POS_TOP False False True False 0 True Samples: False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 PANGO_ELLIPSIZE_NONE -1 False 0 0 False False True False False GTK_POS_TOP False False True 0 False False GTK_JUSTIFY_LEFT False False 1.0 0.5 0 0 PANGO_ELLIPSIZE_NONE -1 False 0 False True True label6 False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 PANGO_ELLIPSIZE_NONE -1 False 0 tab True 888888 False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 PANGO_ELLIPSIZE_NONE -1 False 0 False True True label7 False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 PANGO_ELLIPSIZE_NONE -1 False 0 tab 0 True True False True True label2 False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 PANGO_ELLIPSIZE_NONE -1 False 0 tab True Samples: 8888888 False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 PANGO_ELLIPSIZE_NONE -1 False 0 False True True label3 False False GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 PANGO_ELLIPSIZE_NONE -1 False 0 tab False False 3 False True 0 False False True False 0 3 True True True True True True GTK_POLICY_AUTOMATIC GTK_POLICY_AUTOMATIC GTK_SHADOW_IN GTK_CORNER_TOP_LEFT True True True True False True False False False True False True True GTK_POLICY_AUTOMATIC GTK_POLICY_AUTOMATIC GTK_SHADOW_IN GTK_CORNER_TOP_LEFT True True True True False True False False False True True True False True True GTK_POLICY_AUTOMATIC GTK_POLICY_AUTOMATIC GTK_SHADOW_IN GTK_CORNER_TOP_LEFT True True True True False True False False False True True 0 True True 0 True True Screenshot GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False True False True False False GDK_WINDOW_TYPE_HINT_UTILITY GDK_GRAVITY_NORTH_WEST True False 12 True False 6 True 0 0.5 GTK_SHADOW_NONE True 0.5 0.5 1 1 3 0 12 0 True True GTK_POLICY_AUTOMATIC GTK_POLICY_AUTOMATIC GTK_SHADOW_IN GTK_CORNER_TOP_LEFT True True False False True GTK_JUSTIFY_LEFT GTK_WRAP_NONE False 0 0 0 0 0 0 True <b>Screenshot</b> False True GTK_JUSTIFY_LEFT False False 0.5 0.5 0 0 PANGO_ELLIPSIZE_NONE -1 False 0 label_item 0 True True True GTK_BUTTONBOX_END 0 True True True True gtk-close True GTK_RELIEF_NORMAL True 0 False True sysprof-1.2.0/configure0000755000175000017500000045761612022706426012073 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.68 for sysprof 1.2.0. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software # Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sysprof' PACKAGE_TARNAME='sysprof' PACKAGE_VERSION='1.2.0' PACKAGE_STRING='sysprof 1.2.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_unique_file="sysprof.glade" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS MODULE_SUBDIR BUILD_GUI_FALSE BUILD_GUI_TRUE GUI_DEP_LIBS GUI_DEP_CFLAGS CORE_DEP_LIBS CORE_DEP_CFLAGS PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_maintainer_mode enable_silent_rules enable_dependency_tracking with_separate_debug_dir ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR CORE_DEP_CFLAGS CORE_DEP_LIBS GUI_DEP_CFLAGS GUI_DEP_LIBS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used" >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures sysprof 1.2.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/sysprof] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of sysprof 1.2.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-maintainer-mode disable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-silent-rules less verbose build output (undo: `make V=1') --disable-silent-rules verbose build output (undo: `make V=0') --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-separate-debug-dir=path Look for global separate debug info in this path LIBDIR/debug Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path CORE_DEP_CFLAGS C compiler flags for CORE_DEP, overriding pkg-config CORE_DEP_LIBS linker flags for CORE_DEP, overriding pkg-config GUI_DEP_CFLAGS C compiler flags for GUI_DEP, overriding pkg-config GUI_DEP_LIBS linker flags for GUI_DEP, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF sysprof configure 1.2.0 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by sysprof $as_me 1.2.0, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" ac_aux_dir= for ac_dir in build-aux "$srcdir"/build-aux; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. am__api_version='1.11' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Just in case sleep 1 echo timestamp > conftest.file # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; esac # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } mkdir_p="$MKDIR_P" case $mkdir_p in [\\/$]* | ?:[\\/]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='sysprof' VERSION='1.2.0' # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE # Support silent build rules, requires at least automake-1.11. Disable # by either passing --disable-silent-rules to configure or passing V=1 # to make # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=0;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' # Check for programs ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from `make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi if test "x$CC" != xcc; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 $as_echo_n "checking whether cc understands -c and -o together... " >&6; } fi set dummy $CC; ac_cc=`$as_echo "$2" | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # We do the test twice because some compilers refuse to overwrite an # existing .o file with -o, though they will create one. ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then eval ac_cv_prog_cc_${ac_cc}_c_o=yes if test "x$CC" != xcc; then # Test first that cc exists at all. if { ac_try='cc -c conftest.$ac_ext >&5' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # cc works too. : else # cc exists but doesn't like -o. eval ac_cv_prog_cc_${ac_cc}_c_o=no fi fi fi else eval ac_cv_prog_cc_${ac_cc}_c_o=no fi rm -f core conftest* fi if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h fi # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi if test "x$GCC" = "xyes"; then case " $CFLAGS " in *[\ \ ]-Wall[\ \ ]*) ;; *) CFLAGS="$CFLAGS -Wall" ;; esac fi debugdir=${libdir}/debug # Separate debug dir # Check whether --with-separate-debug-dir was given. if test "${with_separate_debug_dir+set}" = set; then : withval=$with_separate_debug_dir; debugdir="${withval}" fi test "x$prefix" = xNONE && prefix="$ac_default_prefix" test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' ac_define_dir=`eval echo $debugdir` ac_define_dir=`eval echo $ac_define_dir` cat >>confdefs.h <<_ACEOF #define DEBUGDIR "$ac_define_dir" _ACEOF # Kernel version KMAJOR=`uname -r | cut -d"." -f 1` KMINOR=`uname -r | cut -d"." -f 2` KMICRO=`uname -r | cut -d"." -f 3 | cut -d"-" -f 1` # Pkgconfig dependencies core_dep="glib-2.0 >= 2.6.0" gui_dep="gtk+-2.0 > 2.6.0 gdk-pixbuf-2.0 pangoft2 libglade-2.0" if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CORE_DEP" >&5 $as_echo_n "checking for CORE_DEP... " >&6; } if test -n "$CORE_DEP_CFLAGS"; then pkg_cv_CORE_DEP_CFLAGS="$CORE_DEP_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$core_dep\""; } >&5 ($PKG_CONFIG --exists --print-errors "$core_dep") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_CORE_DEP_CFLAGS=`$PKG_CONFIG --cflags "$core_dep" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$CORE_DEP_LIBS"; then pkg_cv_CORE_DEP_LIBS="$CORE_DEP_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$core_dep\""; } >&5 ($PKG_CONFIG --exists --print-errors "$core_dep") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_CORE_DEP_LIBS=`$PKG_CONFIG --libs "$core_dep" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then CORE_DEP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$core_dep" 2>&1` else CORE_DEP_PKG_ERRORS=`$PKG_CONFIG --print-errors "$core_dep" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$CORE_DEP_PKG_ERRORS" >&5 as_fn_error $? "sysprof dependencies not satisfied" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "sysprof dependencies not satisfied" "$LINENO" 5 else CORE_DEP_CFLAGS=$pkg_cv_CORE_DEP_CFLAGS CORE_DEP_LIBS=$pkg_cv_CORE_DEP_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi build_gui=yes pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GUI_DEP" >&5 $as_echo_n "checking for GUI_DEP... " >&6; } if test -n "$GUI_DEP_CFLAGS"; then pkg_cv_GUI_DEP_CFLAGS="$GUI_DEP_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gui_dep\""; } >&5 ($PKG_CONFIG --exists --print-errors "$gui_dep") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GUI_DEP_CFLAGS=`$PKG_CONFIG --cflags "$gui_dep" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$GUI_DEP_LIBS"; then pkg_cv_GUI_DEP_LIBS="$GUI_DEP_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gui_dep\""; } >&5 ($PKG_CONFIG --exists --print-errors "$gui_dep") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GUI_DEP_LIBS=`$PKG_CONFIG --libs "$gui_dep" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then GUI_DEP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$gui_dep" 2>&1` else GUI_DEP_PKG_ERRORS=`$PKG_CONFIG --print-errors "$gui_dep" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$GUI_DEP_PKG_ERRORS" >&5 build_gui=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } build_gui=no else GUI_DEP_CFLAGS=$pkg_cv_GUI_DEP_CFLAGS GUI_DEP_LIBS=$pkg_cv_GUI_DEP_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi if test "$build_gui" = yes; then BUILD_GUI_TRUE= BUILD_GUI_FALSE='#' else BUILD_GUI_TRUE='#' BUILD_GUI_FALSE= fi # emit files ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_GUI_TRUE}" && test -z "${BUILD_GUI_FALSE}"; then as_fn_error $? "conditional \"BUILD_GUI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by sysprof $as_me 1.2.0, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ sysprof config.status 1.2.0 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" Copyright (C) 2010 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi sysprof-1.2.0/sformat.c0000644000175000017500000003165112021176713011765 00000000000000/* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, Red Hat, Inc. * Copyright 2004, 2005, 2006, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "sformat.h" typedef struct State State; typedef struct Transition Transition; typedef struct Fragment Fragment; /* * Format */ struct SFormat { State * begin; State * end; GQueue * types; GQueue * transitions; GQueue * states; }; /* * Type */ typedef enum { TYPE_POINTER, TYPE_STRING, TYPE_INTEGER, TYPE_RECORD, TYPE_LIST, TYPE_FORWARD } TypeKind; struct SType { TypeKind kind; char *name; Transition *enter, *exit; SType *target; /* If kind is TYPE_POINTER */ }; static void type_free (SType *type); /* * Transition */ typedef enum { BEGIN, VALUE, END } TransitionKind; struct Transition { SType * type; TransitionKind kind; State * to; }; static Transition *transition_new (SFormat *format, TransitionKind kind, SType *type, State *from, State *to); static void transition_free (Transition *transition); static void transition_set_to_state (Transition *transition, State *to_state); /* * State */ struct State { GQueue *transitions; }; static State *state_new (SFormat *format); static void state_add_transition (State *state, Transition *transition); static void state_free (State *state); /* * Format */ SFormat * sformat_new (void) { /* FIXME: should probably be refcounted, and an SContext * should have a ref on the format */ SFormat *format = g_new0 (SFormat, 1); format->begin = NULL; format->end = NULL; format->types = g_queue_new (); format->states = g_queue_new (); format->transitions = g_queue_new (); return format; } void sformat_free (SFormat *format) { GList *list; for (list = format->types->head; list; list = list->next) { SType *type = list->data; type_free (type); } g_queue_free (format->types); for (list = format->states->head; list; list = list->next) { State *state = list->data; state_free (state); } g_queue_free (format->states); for (list = format->transitions->head; list; list = list->next) { Transition *transition = list->data; transition_free (transition); } g_queue_free (format->transitions); g_free (format); } void sformat_set_type (SFormat *format, SType *type) { format->begin = state_new (format); format->end = state_new (format); state_add_transition (format->begin, type->enter); transition_set_to_state (type->exit, format->end); } /* * Type */ static SType * type_new (SFormat *format, TypeKind kind, const char *name) { SType *type = g_new0 (SType, 1); type->kind = kind; type->name = name? g_strdup (name) : NULL; type->enter = NULL; type->exit = NULL; type->target = NULL; g_queue_push_tail (format->types, type); return type; } static SType * type_new_from_forward (SFormat *format, TypeKind kind, const char *name, SForward *forward) { SType *type; if (forward) { type = (SType *)forward; type->kind = kind; type->name = g_strdup (name); } else { type = type_new (format, kind, name); } return type; } static SType * type_new_value (SFormat *format, TypeKind kind, const char *name) { SType *type = type_new (format, kind, name); State *before, *after; Transition *value; before = state_new (format); after = state_new (format); type->enter = transition_new (format, BEGIN, type, NULL, before); type->exit = transition_new (format, END, type, after, NULL); value = transition_new (format, VALUE, type, before, after); return type; } static void type_free (SType *type) { g_free (type->name); g_free (type); } SForward * sformat_declare_forward (SFormat *format) { SType *type = type_new (format, TYPE_FORWARD, NULL); return (SForward *)type; } static GQueue * expand_varargs (SType *content1, va_list args) { GQueue *types = g_queue_new (); SType *type; g_queue_push_tail (types, content1); type = va_arg (args, SType *); while (type) { g_queue_push_tail (types, type); type = va_arg (args, SType *); } return types; } SType * sformat_make_record (SFormat *format, const char *name, SForward *forward, SType *content, ...) { SType *type; va_list args; GQueue *types; GList *list; State *begin, *state; /* Build queue of child types */ va_start (args, content); types = expand_varargs (content, args); va_end (args); /* chain types together */ state = begin = state_new (format); for (list = types->head; list != NULL; list = list->next) { SType *child_type = list->data; state_add_transition (state, child_type->enter); state = state_new (format); transition_set_to_state (child_type->exit, state); } g_queue_free (types); /* create and return the new type */ type = type_new_from_forward (format, TYPE_RECORD, name, forward); type->enter = transition_new (format, BEGIN, type, NULL, begin); type->exit = transition_new (format, END, type, state, NULL); return type; } SType * sformat_make_list (SFormat *format, const char *name, SForward *forward, SType *child_type) { SType *type; State *list_state; type = type_new_from_forward (format, TYPE_LIST, name, forward); list_state = state_new (format); type->enter = transition_new (format, BEGIN, type, NULL, list_state); type->exit = transition_new (format, END, type, list_state, NULL); state_add_transition (list_state, child_type->enter); transition_set_to_state (child_type->exit, list_state); return type; } SType * sformat_make_pointer (SFormat *format, const char *name, SForward *forward) { SType *type = type_new_value (format, TYPE_POINTER, name); type->target = (SType *)forward; return type; } SType * sformat_make_integer (SFormat *format, const char *name) { return type_new_value (format, TYPE_INTEGER, name); } SType * sformat_make_string (SFormat *format, const char *name) { return type_new_value (format, TYPE_STRING, name); } gboolean stype_is_record (SType *type) { return type->kind == TYPE_RECORD; } gboolean stype_is_list (SType *type) { return type->kind == TYPE_LIST; } gboolean stype_is_pointer (SType *type) { return type->kind == TYPE_POINTER; } gboolean stype_is_integer (SType *type) { return type->kind == TYPE_INTEGER; } gboolean stype_is_string (SType *type) { return type->kind == TYPE_STRING; } SType * stype_get_target_type (SType *type) { g_return_val_if_fail (stype_is_pointer (type), NULL); return type->target; } const char * stype_get_name (SType *type) { return type->name; } /* Consider adding unions at some point * * To be useful they should probably be anonymous, so that * the union itself doesn't have a representation in the * xml file. * * API: * sformat_new_union (gpointer content1, ...); * * char *content = begin_get_union (); * if (strcmp (content, ...) == 0) * get_pointer (); * else if (strcmp (content, ...) == 0) * * ; * * Annoying though, that we then won't have the nice one-to-one * correspondence between begin()/end() calls and s * Actually, we will probably have to have asdlfkj * elements. That will make things a lot easier, and unions are * still pretty useful if you put big things like lists in them. * * Or maybe just give them a name ... * * We may also consider adding anonymous records. These will * not be able to have pointers associated with them though * (because there wouldn't be a natural place * * * Also consider adding the following data types: * * - Binary blobs of data, stored as base64 perhaps * * - floating point values. How do we store those portably * without losing precision? Gnumeric may know. * * - enums, stored as strings * * - booleans. */ /* * State */ static State * state_new (SFormat *format) { State *state = g_new0 (State, 1); state->transitions = g_queue_new (); g_queue_push_tail (format->states, state); return state; } static void state_add_transition (State *state, Transition *transition) { g_queue_push_tail (state->transitions, transition); } static void state_free (State *state) { g_queue_free (state->transitions); g_free (state); } /* * Transition */ static Transition * transition_new (SFormat *format, TransitionKind kind, SType *type, State *from, State *to) { Transition *transition = g_new0 (Transition, 1); transition->type = type; transition->kind = kind; transition->to = to; if (from) state_add_transition (from, transition); g_queue_push_tail (format->transitions, transition); return transition; } static void transition_free (Transition *transition) { g_free (transition); } static void transition_set_to_state (Transition *transition, State *to_state) { transition->to = to_state; } /* Context */ struct SContext { SFormat *format; State *state; }; SContext * scontext_new (SFormat *format) { SContext *context = g_new0 (SContext, 1); context->format = format; context->state = format->begin; return context; } static SType * do_transition (SContext *context, TransitionKind kind, const char *element) { GList *list; for (list = context->state->transitions->head; list; list = list->next) { Transition *transition = list->data; if (transition->kind == kind) { if (kind == VALUE || strcmp (transition->type->name, element) == 0) { context->state = transition->to; return transition->type; } } } return NULL; } SType * scontext_begin (SContext *context, const char *element) { return do_transition (context, BEGIN, element); } SType * scontext_text (SContext *context) { return do_transition (context, VALUE, NULL); } SType * scontext_end (SContext *context, const char *element) { return do_transition (context, END, element); } gboolean scontext_is_finished (SContext *context) { return context->state == context->format->end; } void scontext_free (SContext *context) { g_free (context); } /* assorted stuff */ #if 0 static const State * state_transition_check (const State *state, const char *element, TransitionKind kind, SType *type) { GList *list; for (list = state->transitions->head; list; list = list->next) { Transition *transition = list->data; if (transition->kind == kind && strcmp (element, transition->element) == 0) { *type = transition->type; return transition->to; } } return NULL; } static const State * state_transition_begin (const State *state, const char *element, SType *type) { return state_transition_check (state, element, BEGIN, type); } static const State * state_transition_end (const State *state, const char *element, SType *type) { return state_transition_check (state, element, END, type); } static const State * state_transition_text (const State *state, SType *type, SType *target_type) { GList *list; for (list = state->transitions->head; list; list = list->next) { Transition *transition = list->data; if (transition->kind == VALUE) { *type = transition->type; if (*type == TYPE_POINTER && target_type) *target_type = transition->target_type; /* There will never be more than one allowed value transition for * a given state */ return transition->to; } } return NULL; } #endif sysprof-1.2.0/stackstash.h0000644000175000017500000000524312021176713012465 00000000000000/* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, Red Hat, Inc. * Copyright 2004, 2005, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef STACK_STASH_H #define STACK_STASH_H #include #include typedef struct StackStash StackStash; typedef struct StackNode StackNode; typedef struct StackLink StackLink; #define U64_TO_POINTER(u) ((void *)(intptr_t)u) #define POINTER_TO_U64(p) ((uint64_t)(intptr_t)p) struct StackNode { uint64_t data; guint total : 32; guint size : 31; guint toplevel : 1; StackNode * parent; StackNode * siblings; StackNode * children; StackNode * next; }; struct StackLink { uint64_t data; StackLink *next; StackLink *prev; }; typedef void (* StackFunction) (StackLink *trace, gint size, gpointer data); typedef void (* StackNodeFunc) (StackNode *node, gpointer data); /* Stach */ StackStash *stack_stash_new (GDestroyNotify destroy); StackNode * stack_node_new (StackStash *stash); StackNode * stack_stash_add_trace (StackStash *stash, uint64_t *addrs, gint n_addrs, int size); void stack_stash_foreach (StackStash *stash, StackFunction stack_func, gpointer data); void stack_node_foreach_trace (StackNode *node, StackFunction stack_func, gpointer data); StackNode *stack_stash_find_node (StackStash *stash, gpointer address); void stack_stash_foreach_by_address (StackStash *stash, StackNodeFunc func, gpointer data); StackNode *stack_stash_get_root (StackStash *stash); StackStash *stack_stash_ref (StackStash *stash); void stack_stash_unref (StackStash *stash); void stack_stash_set_root (StackStash *stash, StackNode *root); #endif sysprof-1.2.0/AUTHORS0000644000175000017500000000004612021176713011210 00000000000000Søren Sandmann (sandmann@redhat.com) sysprof-1.2.0/sfile.c0000644000175000017500000007034712021176713011421 00000000000000/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- */ /* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, Red Hat, Inc. * Copyright 2004, 2005, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #if 0 #include #endif #include "sfile.h" #include "sformat.h" #include typedef struct BuildContext BuildContext; typedef struct Instruction Instruction; typedef enum { BEGIN, END, VALUE } InstructionKind; struct Instruction { InstructionKind kind; SType *type; union { struct { int n_elements; int id; Instruction *end_instruction; } begin; struct { Instruction *begin_instruction; gpointer object; } end; struct { int target_id; Instruction *target_instruction; gpointer target_object; gpointer *location; } pointer; struct { int value; } integer; struct { char *value; } string; } u; }; struct BuildContext { SContext *context; GArray *instructions; }; static void set_error (GError **err, gint code, const char *format, va_list args) { char *msg; if (!err) return; msg = g_strdup_vprintf (format, args); if (*err == NULL) { *err = g_error_new_literal (G_MARKUP_ERROR, code, msg); } else { /* Warning text from GLib */ g_warning ("GError set over the top of a previous GError or uninitialized memory.\n" "This indicates a bug in someone's code. You must ensure an error is NULL before it's set.\n" "The overwriting error message was: %s", msg); } g_free (msg); } static void set_unknown_element_error (GError **err, const char *format, ...) { va_list args; va_start (args, format); set_error (err, G_MARKUP_ERROR_UNKNOWN_ELEMENT, format, args); va_end (args); } static void set_unknown_attribute_error (GError **err, const char *format, ...) { va_list args; va_start (args, format); set_error (err, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, format, args); va_end (args); } static void set_invalid_content_error (GError **err, const char *format, ...) { va_list args; va_start (args, format); set_error (err, G_MARKUP_ERROR_INVALID_CONTENT, format, args); va_end (args); } /* reading */ static gboolean is_all_blank (const char *text) { while (g_ascii_isspace (*text)) text++; return (*text == '\0'); } static gboolean get_number (const char *text, int *number) { char *end; int result; gboolean retval; result = strtol (text, &end, 10); retval = is_all_blank (end); if (retval && number) *number = result; return retval; } struct SFileInput { int n_instructions; Instruction *instructions; Instruction *current_instruction; GHashTable *instructions_by_location; }; static gboolean check_name (Instruction *instr, const char *name) { const char *type_name = stype_get_name (instr->type); return strcmp (name, type_name) == 0; } void sfile_begin_get_record (SFileInput *file, const char *name) { Instruction *instruction = file->current_instruction++; g_return_if_fail (instruction->kind == BEGIN); g_return_if_fail (check_name (instruction, name)); g_return_if_fail (stype_is_record (instruction->type)); } int sfile_begin_get_list (SFileInput *file, const char *name) { Instruction *instruction = file->current_instruction++; g_return_val_if_fail (instruction->kind == BEGIN, 0); g_return_val_if_fail (check_name (instruction, name), 0); g_return_val_if_fail (stype_is_list (instruction->type), 0); return instruction->u.begin.n_elements; } void sfile_get_pointer (SFileInput *file, const char *name, gpointer *location) { Instruction *instruction; instruction = file->current_instruction++; g_return_if_fail (stype_is_pointer (instruction->type)); instruction->u.pointer.location = location; *location = (gpointer) 0xFedeAbe; if (location) { if (g_hash_table_lookup (file->instructions_by_location, location)) g_warning ("Reading into the same location twice\n"); g_hash_table_insert (file->instructions_by_location, location, instruction); } } void sfile_get_integer (SFileInput *file, const char *name, gint32 *integer) { Instruction *instruction; instruction = file->current_instruction++; g_return_if_fail (stype_is_integer (instruction->type)); if (integer) *integer = instruction->u.integer.value; } void sfile_get_string (SFileInput *file, const char *name, char **string) { Instruction *instruction; instruction = file->current_instruction++; g_return_if_fail (stype_is_string (instruction->type)); if (string) *string = g_strdup (instruction->u.string.value); } static void hook_up_pointers (SFileInput *file) { int i; for (i = 0; i < file->n_instructions; ++i) { Instruction *instruction = &(file->instructions[i]); if (stype_is_pointer (instruction->type)) { gpointer target_object; Instruction *target_instruction; target_instruction = instruction->u.pointer.target_instruction; if (target_instruction) target_object = target_instruction->u.begin.end_instruction->u.end.object; else target_object = NULL; *(instruction->u.pointer.location) = target_object; } } } void sfile_end_get (SFileInput *file, const char *name, gpointer object) { Instruction *instruction = file->current_instruction++; g_return_if_fail (instruction->kind == END); g_return_if_fail (check_name (instruction, name)); instruction->u.end.object = object; if (file->current_instruction == file->instructions + file->n_instructions) hook_up_pointers (file); } static int get_id (const char **names, const char **values, GError **err) { const char *id_string = NULL; int id, i; for (i = 0; names[i] != NULL; ++i) { if (strcmp (names[i], "id") != 0) { set_unknown_attribute_error (err, "Unknown attribute: %s", names[i]); return -1; } if (id_string) { set_invalid_content_error (err, "Attribute 'id' defined twice"); return -1; } id_string = values[i]; } if (!id_string) return 0; if (!get_number (id_string, &id) || id < 1) { set_invalid_content_error (err, "Bad attribute value for attribute 'id' (must be >= 1)\n"); return -1; } return id; } static void handle_begin_element (GMarkupParseContext *parse_context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, GError **err) { BuildContext *build = user_data; Instruction instruction; instruction.u.begin.id = get_id (attribute_names, attribute_values, err); if (instruction.u.begin.id == -1) return; instruction.type = scontext_begin (build->context, element_name); if (!instruction.type) { set_unknown_element_error (err, "<%s> unexpected here", element_name); return; } if (stype_is_list (instruction.type) || stype_is_record (instruction.type)) { instruction.kind = BEGIN; g_array_append_val (build->instructions, instruction); } } static void handle_end_element (GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **err) { BuildContext *build = user_data; Instruction instruction; instruction.type = scontext_end (build->context, element_name); if (!instruction.type) { set_unknown_element_error (err, " unexpected here", element_name); return; } if (stype_is_list (instruction.type) || stype_is_record (instruction.type)) { instruction.kind = END; g_array_append_val (build->instructions, instruction); } } static gboolean decode_text (const char *text, char **decoded) { int length = strlen (text); if (length < 2) return FALSE; if (text[0] != '\"' || text[length - 1] != '\"') return FALSE; if (decoded) *decoded = g_strndup (text + 1, length - 2); return TRUE; } static const char * skip_whitespace (const char *text) { while (g_ascii_isspace (*text)) text++; return text; } static void handle_text (GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **err) { BuildContext *build = user_data; Instruction instruction; if (*text == '\0') return; text = skip_whitespace (text); if (*text == '\0') return; instruction.type = scontext_text (build->context); if (!instruction.type) { /* FIXME: what are line and ch used for here? */ int line, ch; g_markup_parse_context_get_position (context, &line, &ch); set_invalid_content_error (err, "Unexpected text data"); return; } instruction.kind = VALUE; if (stype_is_pointer (instruction.type)) { if (!get_number (text, &instruction.u.pointer.target_id)) { set_invalid_content_error (err, "Content '%s' of pointer element is not a number", text); return; } } else if (stype_is_integer (instruction.type)) { if (!get_number (text, &instruction.u.integer.value)) { set_invalid_content_error (err, "Content '%s' of integer element is not a number", text); return; } } else if (stype_is_string (instruction.type)) { if (!decode_text (text, &instruction.u.string.value)) { set_invalid_content_error (err, "Content '%s' of text element is ill-formed", text); return; } } else { g_assert_not_reached(); } g_array_append_val (build->instructions, instruction); } static void free_instructions (Instruction *instructions, int n_instructions) { int i; for (i = 0; i < n_instructions; ++i) { Instruction *instruction = &(instructions[i]); if (stype_is_string (instruction->type)) g_free (instruction->u.string.value); } g_free (instructions); } /* This functions makes end instructions point to the corresponding * begin instructions, and counts the number of instructions * contained in a begin/end pair */ static Instruction * process_instruction_pairs (Instruction *first) { Instruction *instruction; int n_elements; g_assert (first->kind == BEGIN); instruction = first + 1; n_elements = 0; while (instruction->kind != END) { if (instruction->kind == BEGIN) { instruction = process_instruction_pairs (instruction); if (!instruction) return NULL; } else { instruction++; } n_elements++; } first->u.begin.n_elements = n_elements; first->u.begin.end_instruction = instruction; instruction->u.end.begin_instruction = first; return instruction + 1; } static gboolean post_process_read_instructions (Instruction *instructions, int n_instructions, GError **err) { gboolean retval = TRUE; GHashTable *instructions_by_id; int i; /* count list instructions, check pointers */ process_instruction_pairs (instructions); /* Build id->instruction map */ instructions_by_id = g_hash_table_new (g_direct_hash, g_direct_equal); for (i = 0; i < n_instructions; ++i) { Instruction *instruction = &(instructions[i]); if (instruction->kind == BEGIN) { int id = instruction->u.begin.id; if (id) g_hash_table_insert (instructions_by_id, GINT_TO_POINTER (id), instruction); } } /* Make pointer instructions point to the corresponding element */ for (i = 0; i < n_instructions; ++i) { Instruction *instruction = &(instructions[i]); if (stype_is_pointer (instruction->type)) { int target_id = instruction->u.pointer.target_id; if (target_id) { Instruction *target = g_hash_table_lookup (instructions_by_id, GINT_TO_POINTER (target_id)); if (target) { if (stype_get_target_type (instruction->type) == target->type) { instruction->u.pointer.target_instruction = target; } else { set_invalid_content_error (err, "Id %d references an element of the wrong type", instruction->u.pointer.target_id); retval = FALSE; break; } } else { set_invalid_content_error (err, "Id %d doesn't reference any record or list", instruction->u.pointer.target_id); retval = FALSE; break; } } else { instruction->u.pointer.target_instruction = NULL; } } } g_hash_table_destroy (instructions_by_id); return retval; } static Instruction * build_instructions (const char *contents, gsize length, SFormat *format, int *n_instructions, GError **err) { BuildContext build; GMarkupParseContext *parse_context; GMarkupParser parser = { handle_begin_element, handle_end_element, handle_text, NULL, /* passthrough */ NULL, /* error */ }; build.context = scontext_new (format); build.instructions = g_array_new (TRUE, TRUE, sizeof (Instruction)); parse_context = g_markup_parse_context_new (&parser, 0, &build, NULL); while (length) { int bytes = MIN (length, 65536); if (!g_markup_parse_context_parse (parse_context, contents, bytes, err)) { free_instructions ((Instruction *)build.instructions->data, build.instructions->len); return NULL; } contents += bytes; length -= bytes; } if (!g_markup_parse_context_end_parse (parse_context, err)) { free_instructions ((Instruction *)build.instructions->data, build.instructions->len); return NULL; } if (!scontext_is_finished (build.context)) { set_invalid_content_error (err, "Premature end of file\n"); free_instructions ((Instruction *)build.instructions->data, build.instructions->len); return NULL; } if (!post_process_read_instructions ((Instruction *)build.instructions->data, build.instructions->len, err)) { free_instructions ((Instruction *)build.instructions->data, build.instructions->len); return NULL; } *n_instructions = build.instructions->len; return (Instruction *)g_array_free (build.instructions, FALSE); } SFileInput * sfile_load (const char *filename, SFormat *format, GError **err) { gchar *contents; gsize length; SFileInput *input; GMappedFile *file; file = g_mapped_file_new (filename, FALSE, err); if (!file) return NULL; contents = g_mapped_file_get_contents (file); length = g_mapped_file_get_length (file); madvise (contents, length, MADV_SEQUENTIAL); input = g_new (SFileInput, 1); input->instructions = build_instructions (contents, length, format, &input->n_instructions, err); if (!input->instructions) { g_free (input); g_mapped_file_free (file); return NULL; } g_mapped_file_free (file); input->current_instruction = input->instructions; input->instructions_by_location = g_hash_table_new (g_direct_hash, g_direct_equal); return input; } /* Writing */ struct SFileOutput { SFormat *format; GArray *instructions; GHashTable *objects; SContext *context; }; SFileOutput * sfile_output_new (SFormat *format) { SFileOutput *output = g_new (SFileOutput, 1); output->format = format; output->instructions = g_array_new (TRUE, TRUE, sizeof (Instruction)); output->context = scontext_new (format); output->objects = g_hash_table_new (g_direct_hash, g_direct_equal); return output; } void sfile_begin_add_record (SFileOutput *file, const char *name) { Instruction instruction; instruction.type = scontext_begin (file->context, name); g_return_if_fail (instruction.type); g_return_if_fail (stype_is_record (instruction.type)); instruction.kind = BEGIN; g_array_append_val (file->instructions, instruction); } void sfile_begin_add_list (SFileOutput *file, const char *name) { Instruction instruction; instruction.type = scontext_begin (file->context, name); g_return_if_fail (instruction.type); g_return_if_fail (stype_is_list (instruction.type)); instruction.kind = BEGIN; g_array_append_val (file->instructions, instruction); } void sfile_end_add (SFileOutput *file, const char *name, gpointer object) { Instruction instruction; if (object && g_hash_table_lookup (file->objects, object)) { g_warning ("Adding the same object (%p) twice", object); return; } instruction.type = scontext_end (file->context, name); if (!instruction.type) { g_warning ("invalid call of sfile_end_add()"); return; } instruction.kind = END; instruction.u.end.object = object; g_array_append_val (file->instructions, instruction); if (object) g_hash_table_insert (file->objects, object, object); } static SType * sfile_check_value (SFileOutput *file, const char *name) { SType *tmp_type; tmp_type = scontext_begin (file->context, name); if (!tmp_type) return NULL; tmp_type = scontext_text (file->context); if (!tmp_type) return NULL; tmp_type = scontext_end (file->context, name); if (!tmp_type) return NULL; return tmp_type; } void sfile_add_string (SFileOutput *file, const char *name, const char *string) { Instruction instruction; g_return_if_fail (g_utf8_validate (string, -1, NULL)); instruction.type = sfile_check_value (file, name); if (!instruction.type || !stype_is_string (instruction.type)) { g_warning ("Invalid call to sfile_add_string()"); return; } instruction.kind = VALUE; instruction.u.string.value = g_strdup (string); g_array_append_val (file->instructions, instruction); } void sfile_add_integer (SFileOutput *file, const char *name, int integer) { Instruction instruction; instruction.type = sfile_check_value (file, name); if (!instruction.type || !stype_is_integer (instruction.type)) { g_warning ("Invalid call to sfile_add_integer()"); return; } instruction.kind = VALUE; instruction.u.integer.value = integer; g_array_append_val (file->instructions, instruction); } void sfile_add_pointer (SFileOutput *file, const char *name, gpointer pointer) { Instruction instruction; instruction.type = sfile_check_value (file, name); if (!instruction.type || !stype_is_pointer (instruction.type)) { g_warning ("Invalid call to sfile_add_pointer()"); return; } instruction.kind = VALUE; instruction.u.pointer.target_object = pointer; g_array_append_val (file->instructions, instruction); } static void post_process_write_instructions (SFileOutput *sfile) { int i; Instruction *instructions = (Instruction *)sfile->instructions->data; int n_instructions = sfile->instructions->len; int id; GHashTable *instructions_by_object; process_instruction_pairs (instructions); /* Set all id's to -1 and create map from objects to instructions */ instructions_by_object = g_hash_table_new (g_direct_hash, g_direct_equal); for (i = 0; i < n_instructions; ++i) { Instruction *instruction = &(instructions[i]); if (instruction->kind == BEGIN) { instruction->u.begin.id = -1; } else if (instruction->kind == END && instruction->u.end.object) { g_hash_table_insert (instructions_by_object, instruction->u.end.object, instruction); } } /* Assign an id to all pointed-to instructions */ id = 1; for (i = 0; i < n_instructions; ++i) { Instruction *instruction = &(instructions[i]); if (stype_is_pointer (instruction->type)) { if (instruction->u.pointer.target_object) { Instruction *target; target = g_hash_table_lookup (instructions_by_object, instruction->u.pointer.target_object); if (!target) { g_warning ("pointer has unknown target\n"); goto out; } g_assert (target->kind == END); if (target->u.end.begin_instruction->u.begin.id == -1) target->u.end.begin_instruction->u.begin.id = id++; instruction->u.pointer.target_id = target->u.end.begin_instruction->u.begin.id; } else { instruction->u.pointer.target_id = 0; } } } out: g_hash_table_destroy (instructions_by_object); } static void add_indent (GString *output, int indent) { int i; for (i = 0; i < indent; ++i) g_string_append_c (output, ' '); } static void add_integer (GString *output, int value) { g_string_append_printf (output, "%d", value); } static void add_string (GString *output, const char *str) { char *escaped = g_markup_escape_text (str, -1); g_string_append_c (output, '\"'); g_string_append (output, escaped); g_string_append_c (output, '\"'); g_free (escaped); } static void add_begin_tag (GString *output, int indent, const char *name, int id) { add_indent (output, indent); if (id != -1) g_string_append_printf (output, "<%s id=\"%d\">", name, id); else g_string_append_printf (output, "<%s>", name); } static void add_end_tag (GString *output, int indent, const char *name) { add_indent (output, indent); g_string_append_printf (output, "", name); } static void add_nl (GString *output) { g_string_append_c (output, '\n'); } #if 0 static void disaster (int status) { const char *error; switch (status) { case BZ_PARAM_ERROR: error = "BZ_PARAM_ERROR"; break; case BZ_MEM_ERROR: error = "BZ_MEM_ERROR"; break; case BZ_OUTBUFF_FULL: error = "BZ_OUTBUFF_FULL"; break; default: error = "Unknown error"; break; } g_error ("Failed to compress file: %s\n", error); } static void bz2_compress (const guchar *input, int input_length, guchar **output, int *output_length) { size_t compressed_size; guchar *compressed_data; int status; g_return_if_fail (input != NULL); /* The bzip2 manual says: * * To guarantee that the compressed data will fit in its buffer, * allocate an output buffer of size 1% larger than the uncompressed * data, plus six hundred extra bytes. */ compressed_size = (size_t)(1.02 * input_length + 600); compressed_data = g_malloc (compressed_size); status = BZ2_bzBuffToBuffCompress (compressed_data, &compressed_size, (guchar *)input, input_length, 9 /* block size */, 0 /* verbosity */, 0 /* workfactor */); if (status != BZ_OK) disaster (status); if (output) *output = compressed_data; else g_free (compressed_data); if (output_length) *output_length = compressed_size; } #endif static const char * get_name (Instruction *inst) { return stype_get_name (inst->type); } gboolean sfile_output_save (SFileOutput *sfile, const char *filename, GError **err) { int i; Instruction *instructions; GString *output; int indent; gboolean retval; #if 0 guchar *compressed; size_t compressed_size; #endif g_return_val_if_fail (sfile != NULL, FALSE); instructions = (Instruction *)sfile->instructions->data; post_process_write_instructions (sfile); indent = 0; output = g_string_new (""); for (i = 0; i < sfile->instructions->len; ++i) { Instruction *instruction = &(instructions[i]); switch (instruction->kind) { case BEGIN: add_begin_tag (output, indent, get_name (instruction), instruction->u.begin.id); add_nl (output); indent += 4; break; case END: indent -= 4; add_end_tag (output, indent, get_name (instruction)); add_nl (output); break; case VALUE: add_begin_tag (output, indent, get_name (instruction), -1); if (stype_is_integer (instruction->type)) { add_integer (output, instruction->u.integer.value); } else if (stype_is_pointer (instruction->type)) { add_integer (output, instruction->u.pointer.target_id); } else if (stype_is_string (instruction->type)) { add_string (output, instruction->u.string.value); } add_end_tag (output, 0, get_name (instruction)); add_nl (output); break; } } #if 0 /* FIXME - not10: bz2 compressing the output is probably * interesting at some point. For now just make sure * it works without actually using it. */ bz2_compress (output->str, output->len, &compressed, &compressed_size); g_free (compressed); #endif retval = g_file_set_contents (filename, output->str, output->len, err); g_string_free (output, TRUE); return retval; } void sfile_input_free (SFileInput *file) { free_instructions (file->instructions, file->n_instructions); g_hash_table_destroy (file->instructions_by_location); g_free (file); } void sfile_output_free (SFileOutput *sfile) { Instruction *instructions; int n_instructions; n_instructions = sfile->instructions->len; instructions = (Instruction *)g_array_free (sfile->instructions, FALSE); free_instructions (instructions, n_instructions); g_hash_table_destroy (sfile->objects); g_free (sfile); } sysprof-1.2.0/testelf.c0000644000175000017500000000404712021176713011757 00000000000000#include #include "elfparser.h" #include const char *n; static void check (ElfParser *elf, gulong addr) { const ElfSym *sym = elf_parser_lookup_symbol (elf, addr); if (!sym) { g_print ("not found\n"); return; } n = elf_parser_get_sym_name (elf, sym); g_print ("%p => ", (void *)addr); if (sym) { g_print ("found: %s (%p)\n", elf_parser_get_sym_name (elf, sym), (void *)elf_parser_get_sym_address (elf, sym)); } else { g_print ("not found\n"); } } int main (int argc, char **argv) { ElfParser *elf; ElfParser *debug = NULL; const char *build_id; const char *filename; const char *dir; if (argc == 1) filename = "/usr/lib/libgtk-x11-2.0.so"; else filename = argv[1]; elf = elf_parser_new (filename, NULL); if (!elf) { g_print ("NO ELF!!!!\n"); return -1; } dir = g_path_get_dirname (filename); build_id = elf_parser_get_build_id (elf); guint crc = elf_parser_get_crc32 (elf); g_print ("build ID: %s crc: %x\n", build_id, crc); filename = elf_parser_get_debug_link(elf, &crc); if (filename) { filename = g_build_filename ("/usr", "lib", "debug", dir, filename, NULL); g_print ("Debug link: %s crc: %x\n", filename, crc); debug = elf_parser_new (filename, NULL); if (debug) { const char *build = elf_parser_get_build_id (debug); guint crc_debug = elf_parser_get_crc32 (debug); g_print ("Debug link build ID: %s crc: %x\n", build, crc_debug); if (strcmp(build, build_id) != 0 || crc_debug != crc) g_print ("Build ID or crc not matching!\n"); } else { g_print ("Separate debug symbol file not found\n"); } } else { g_print ("No debug link\n"); } #if 0 for (i = 0; i < 5000000; ++i) #endif { elf_parser_get_crc32 (elf); check (elf, 0x077c80f0 - (0x07787000 - 0)); /* gtk_about_dialog_set_artists (add - (map - offset)) */ check (elf, 0x077c80f0 - (0x07787000 - 0)); /* same (but in the middle of the function */ } return 0; } sysprof-1.2.0/configure.ac0000644000175000017500000000410512022706134012423 00000000000000AC_PREREQ([2.63]) AC_INIT([sysprof], [1.2.0]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_SRCDIR([sysprof.glade]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([1.10 -Wall no-define]) AM_MAINTAINER_MODE([enable]) # Support silent build rules, requires at least automake-1.11. Disable # by either passing --disable-silent-rules to configure or passing V=1 # to make m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) # Check for programs AC_PROG_CC AM_PROG_CC_C_O AC_PROG_INSTALL changequote(,)dnl if test "x$GCC" = "xyes"; then case " $CFLAGS " in *[\ \ ]-Wall[\ \ ]*) ;; *) CFLAGS="$CFLAGS -Wall" ;; esac fi changequote([,])dnl debugdir=${libdir}/debug # Separate debug dir dnl written by Guido Draheim , original by Alexandre Oliva dnl Version 1.3 (2001/03/02) dnl source http://www.gnu.org/software/ac-archive/Miscellaneous/ac_define_dir.html AC_DEFUN([AC_DEFINE_DIR], [ test "x$prefix" = xNONE && prefix="$ac_default_prefix" test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' ac_define_dir=`eval echo [$]$2` ac_define_dir=`eval echo [$]ac_define_dir` ifelse($3, , AC_DEFINE_UNQUOTED($1, "$ac_define_dir"), AC_DEFINE_UNQUOTED($1, "$ac_define_dir", $3)) ]) AC_ARG_WITH(separate-debug-dir, [ --with-separate-debug-dir=path Look for global separate debug info in this path [LIBDIR/debug]], [debugdir="${withval}"]) AC_DEFINE_DIR(DEBUGDIR, debugdir, [Look for global separate debug info in this path]) # Kernel version KMAJOR=`uname -r | cut -d"." -f 1` KMINOR=`uname -r | cut -d"." -f 2` KMICRO=`uname -r | cut -d"." -f 3 | cut -d"-" -f 1` # Pkgconfig dependencies core_dep="glib-2.0 >= 2.6.0" gui_dep="gtk+-2.0 > 2.6.0 gdk-pixbuf-2.0 pangoft2 libglade-2.0" PKG_CHECK_MODULES(CORE_DEP, $core_dep, [], AC_MSG_ERROR([sysprof dependencies not satisfied])) build_gui=yes PKG_CHECK_MODULES(GUI_DEP, $gui_dep, [], build_gui=no) AM_CONDITIONAL([BUILD_GUI], [test "$build_gui" = yes]) # emit files AC_SUBST(CORE_DEP_LIBS) AC_SUBST(GUI_DEP_LIBS) AC_SUBST(MODULE_SUBDIR) AC_CONFIG_FILES([ Makefile ]) AC_OUTPUT sysprof-1.2.0/binfile.c0000644000175000017500000002663712021176713011732 00000000000000/* MemProf -- memory profiler and leak detector * Copyright 1999, 2000, 2001, Red Hat, Inc. * Copyright 2002, Kristian Rietveld * * Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, 2005, 2006, 2007, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Most interesting code in this file is lifted from bfdutils.c * and process.c from Memprof, */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "binfile.h" #include "elfparser.h" #include "util.h" struct bin_file_t { int ref_count; GList * elf_files; char * filename; char * undefined_name; gulong text_offset; gboolean inode_check; ino_t inode; }; static ino_t read_inode (const char *filename) { struct stat statbuf; if (strcmp (filename, "[vdso]") == 0) return (ino_t)0; if (stat (filename, &statbuf) < 0) return (ino_t)-1; return statbuf.st_ino; } static gboolean already_warned (const char *name) { static GPtrArray *warnings; int i; if (!warnings) warnings = g_ptr_array_new (); for (i = 0; i < warnings->len; ++i) { if (strcmp (warnings->pdata[i], name) == 0) return TRUE; } g_ptr_array_add (warnings, g_strdup (name)); return FALSE; } static const char *const debug_file_directory = DEBUGDIR; static ElfParser * get_build_id_file (ElfParser *elf) { const char *build_id; GList *tries = NULL, *list; char *init, *rest; ElfParser *result = NULL; char *tmp; build_id = elf_parser_get_build_id (elf); if (!build_id) return NULL; if (strlen (build_id) < 4) return NULL; init = g_strndup (build_id, 2); rest = g_strdup_printf ("%s%s", build_id + 2, ".debug"); tmp = g_build_filename ( "/usr", "lib", "debug", ".build-id", init, rest, NULL); tries = g_list_append (tries, tmp); tmp = g_build_filename ( debug_file_directory, ".build-id", init, rest, NULL); tries = g_list_append (tries, tmp); for (list = tries; list != NULL; list = list->next) { char *name = list->data; ElfParser *parser = elf_parser_new (name, NULL); if (parser) { const char *file_id = elf_parser_get_build_id (parser); if (file_id && strcmp (build_id, file_id) == 0) { result = parser; break; } elf_parser_free (parser); } } g_list_foreach (tries, (GFunc)g_free, NULL); g_list_free (tries); g_free (init); g_free (rest); return result; } static ElfParser * get_debuglink_file (ElfParser *elf, const char *filename, char **new_name) { #define N_TRIES 4 const char *basename; char *dir; guint32 crc32; GList *tries = NULL, *list; ElfParser *result = NULL; const char *build_id; if (!elf) return NULL; basename = elf_parser_get_debug_link (elf, &crc32); build_id = elf_parser_get_build_id (elf); #if 0 g_print (" debug link for %s is %s\n", filename, basename); #endif if (!basename) return NULL; dir = g_path_get_dirname (filename); tries = g_list_append (tries, g_build_filename (dir, basename, NULL)); tries = g_list_append (tries, g_build_filename (dir, ".debug", basename, NULL)); tries = g_list_append (tries, g_build_filename ("/usr", "lib", "debug", dir, basename, NULL)); tries = g_list_append (tries, g_build_filename (debug_file_directory, dir, basename, NULL)); for (list = tries; list != NULL; list = list->next) { const char *name = list->data; ElfParser *parser = elf_parser_new (name, NULL); guint32 file_crc; const char *file_build_id; if (parser) { /* If both files have build ids, and they don't match, * there is no point computing a CRC32 that we know * will fail */ file_build_id = elf_parser_get_build_id (parser); if (build_id && file_build_id && strcmp (build_id, file_build_id) != 0) goto skip; file_crc = elf_parser_get_crc32 (parser); if (file_crc == crc32) { result = parser; *new_name = g_strdup (name); break; } else { if (!already_warned (name)) { g_print ("warning: %s has wrong crc %x, %s has crc %x)\n", name, file_crc, filename, crc32); } } skip: elf_parser_free (parser); } } g_free (dir); g_list_foreach (tries, (GFunc)g_free, NULL); g_list_free (tries); return result; } static GList * get_debug_binaries (GList *files, ElfParser *elf, const char *filename) { ElfParser *build_id_file; GHashTable *seen_names; GList *free_us = NULL; build_id_file = get_build_id_file (elf); if (build_id_file) return g_list_prepend (files, build_id_file); /* .gnu_debuglink is actually a chain of debuglinks, and * there have been real-world cases where following it was * necessary to get useful debug information. */ seen_names = g_hash_table_new (g_str_hash, g_str_equal); while (elf) { char *debug_name; if (g_hash_table_lookup (seen_names, filename)) break; g_hash_table_insert (seen_names, (char *)filename, (char *)filename); elf = get_debuglink_file (elf, filename, &debug_name); if (elf) { files = g_list_prepend (files, elf); free_us = g_list_prepend (free_us, debug_name); filename = debug_name; } } g_list_foreach (free_us, (GFunc)g_free, NULL); g_list_free (free_us); g_hash_table_destroy (seen_names); return files; } static char ** get_lines (const char *format, pid_t pid) { char *filename = g_strdup_printf (format, pid); char **result = NULL; char *contents; if (g_file_get_contents (filename, &contents, NULL, NULL)) { result = g_strsplit (contents, "\n", -1); g_free (contents); } g_free (filename); return result; } static const uint8_t * get_vdso_bytes (size_t *length) { static const uint8_t *bytes = NULL; static size_t n_bytes = 0; static gboolean has_data; if (!has_data) { char **lines = get_lines ("/proc/%d/maps", getpid()); int i; for (i = 0; lines[i] != NULL; ++i) { char file[256]; gulong start; gulong end; int count = sscanf ( lines[i], "%lx-%lx %*15s %*x %*x:%*x %*u %255s", &start, &end, file); if (count == 3 && strcmp (file, "[vdso]") == 0) { n_bytes = end - start; /* Dup the memory here so that valgrind will only * report one 1 byte invalid read instead of * a ton when the elf parser scans the vdso * * The reason we get a spurious invalid read from * valgrind is that we are getting the address directly * from /proc/maps, and valgrind knows that its mmap() * wrapper never returned that address. But since it * is a legal mapping, it is legal to read it. */ bytes = g_memdup ((uint8_t *)start, n_bytes); has_data = TRUE; } } } if (length) *length = n_bytes; return bytes; } bin_file_t * bin_file_new (const char *filename) { ElfParser *elf = NULL; bin_file_t *bf; bf = g_new0 (bin_file_t, 1); bf->inode_check = FALSE; bf->filename = g_strdup (filename); bf->undefined_name = g_strdup_printf ("In file %s", filename); bf->ref_count = 1; bf->elf_files = NULL; if (strcmp (filename, "[vdso]") == 0) { const guint8 *vdso_bytes; gsize length; vdso_bytes = get_vdso_bytes (&length); if (vdso_bytes) elf = elf_parser_new_from_data (vdso_bytes, length); } else { elf = elf_parser_new (filename, NULL); } if (elf) { /* We need the text offset of the actual binary, not the * (potential) debug binaries */ bf->text_offset = elf_parser_get_text_offset (elf); bf->elf_files = get_debug_binaries (bf->elf_files, elf, filename); bf->elf_files = g_list_append (bf->elf_files, elf); bf->inode = read_inode (filename); } return bf; } void bin_file_free (bin_file_t *bin_file) { if (--bin_file->ref_count == 0) { g_list_foreach (bin_file->elf_files, (GFunc)elf_parser_free, NULL); g_list_free (bin_file->elf_files); g_free (bin_file->filename); g_free (bin_file->undefined_name); g_free (bin_file); } } const bin_symbol_t * bin_file_lookup_symbol (bin_file_t *bin_file, gulong address) { GList *list; #if 0 g_print ("-=-=-=- \n"); g_print ("bin file lookup lookup %d\n", address); #endif address -= bin_file->text_offset; #if 0 g_print ("lookup %d in %s\n", address, bin_file->filename); #endif for (list = bin_file->elf_files; list != NULL; list = list->next) { ElfParser *elf = list->data; const ElfSym *sym = elf_parser_lookup_symbol (elf, address); if (sym) { #if 0 g_print ("found %lx => %s\n", address, bin_symbol_get_name (bin_file, sym)); #endif return (const bin_symbol_t *)sym; } } #if 0 g_print ("%lx undefined in %s (textoffset %x)\n", address + bin_file->text_offset, bin_file->filename, bin_file->text_offset); #endif return (const bin_symbol_t *)bin_file->undefined_name; } gboolean bin_file_check_inode (bin_file_t *bin_file, ino_t inode) { if (bin_file->inode == inode) return TRUE; if (!bin_file->elf_files) return FALSE; if (!bin_file->inode_check) { g_print ("warning: Inode mismatch for %s (disk: "FMT64", memory: "FMT64")\n", bin_file->filename, (guint64)bin_file->inode, (guint64)inode); bin_file->inode_check = TRUE; } return FALSE; } static const ElfSym * get_elf_sym (bin_file_t *file, const bin_symbol_t *symbol, ElfParser **elf_ret) { GList *list; for (list = file->elf_files; list != NULL; list = list->next) { const ElfSym *sym = (const ElfSym *)symbol; ElfParser *elf = list->data; if (elf_parser_owns_symbol (elf, sym)) { *elf_ret = elf; return sym; } } g_critical ("Internal error: unrecognized symbol pointer"); *elf_ret = NULL; return NULL; } const char * bin_symbol_get_name (bin_file_t *file, const bin_symbol_t *symbol) { if (file->undefined_name == (char *)symbol) { return file->undefined_name; } else { ElfParser *elf; const ElfSym *sym; sym = get_elf_sym (file, symbol, &elf); return elf_parser_get_sym_name (elf, sym); } } gulong bin_symbol_get_address (bin_file_t *file, const bin_symbol_t *symbol) { if (file->undefined_name == (char *)symbol) { return 0x0; } else { ElfParser *elf; const ElfSym *sym; sym = get_elf_sym (file, symbol, &elf); return elf_parser_get_sym_address (elf, sym); } } sysprof-1.2.0/footreedatalist.c0000644000175000017500000003463712021176713013512 00000000000000/* gtktreedatalist.c * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * This file contains code shared between GtkTreeStore and GtkListStore. Please * do not use it. */ #include "footreedatalist.h" #include static FooTreeDataList *cache; /* node allocation */ #define N_DATA_LISTS (64) FooTreeDataList * _foo_tree_data_list_alloc (void) { FooTreeDataList *list; if (!cache) { int i; list = g_malloc (N_DATA_LISTS * sizeof (FooTreeDataList)); for (i = 0; i < N_DATA_LISTS; ++i) { list[i].next = cache; cache = &(list[i]); } } list = cache; cache = cache->next; memset (list, 0, sizeof (FooTreeDataList)); return list; } void _foo_tree_data_list_free (FooTreeDataList *list, GType *column_headers) { FooTreeDataList *tmp, *next; gint i = 0; tmp = list; while (tmp) { next = tmp->next; if (g_type_is_a (column_headers [i], G_TYPE_STRING)) g_free ((gchar *) tmp->data.v_pointer); else if (g_type_is_a (column_headers [i], G_TYPE_OBJECT) && tmp->data.v_pointer != NULL) g_object_unref (tmp->data.v_pointer); else if (g_type_is_a (column_headers [i], G_TYPE_BOXED) && tmp->data.v_pointer != NULL) g_boxed_free (column_headers [i], (gpointer) tmp->data.v_pointer); tmp->next = cache; cache = tmp; i++; tmp = next; } } gboolean _foo_tree_data_list_check_type (GType type) { gint i = 0; static const GType type_list[] = { G_TYPE_BOOLEAN, G_TYPE_CHAR, G_TYPE_UCHAR, G_TYPE_INT, G_TYPE_UINT, G_TYPE_LONG, G_TYPE_ULONG, G_TYPE_INT64, G_TYPE_UINT64, G_TYPE_ENUM, G_TYPE_FLAGS, G_TYPE_FLOAT, G_TYPE_DOUBLE, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOXED, G_TYPE_OBJECT, G_TYPE_INVALID }; if (! G_TYPE_IS_VALUE_TYPE (type)) return FALSE; while (type_list[i] != G_TYPE_INVALID) { if (g_type_is_a (type, type_list[i])) return TRUE; i++; } return FALSE; } static inline GType get_fundamental_type (GType type) { GType result; result = G_TYPE_FUNDAMENTAL (type); if (result == G_TYPE_INTERFACE) { if (g_type_is_a (type, G_TYPE_OBJECT)) result = G_TYPE_OBJECT; } return result; } void _foo_tree_data_list_node_to_value (FooTreeDataList *list, GType type, GValue *value) { g_value_init (value, type); switch (get_fundamental_type (type)) { case G_TYPE_BOOLEAN: g_value_set_boolean (value, (gboolean) list->data.v_int); break; case G_TYPE_CHAR: g_value_set_char (value, (gchar) list->data.v_char); break; case G_TYPE_UCHAR: g_value_set_uchar (value, (guchar) list->data.v_uchar); break; case G_TYPE_INT: g_value_set_int (value, (gint) list->data.v_int); break; case G_TYPE_UINT: g_value_set_uint (value, (guint) list->data.v_uint); break; case G_TYPE_LONG: g_value_set_long (value, list->data.v_long); break; case G_TYPE_ULONG: g_value_set_ulong (value, list->data.v_ulong); break; case G_TYPE_INT64: g_value_set_int64 (value, list->data.v_int64); break; case G_TYPE_UINT64: g_value_set_uint64 (value, list->data.v_uint64); break; case G_TYPE_ENUM: g_value_set_enum (value, list->data.v_int); break; case G_TYPE_FLAGS: g_value_set_flags (value, list->data.v_uint); break; case G_TYPE_FLOAT: g_value_set_float (value, (gfloat) list->data.v_float); break; case G_TYPE_DOUBLE: g_value_set_double (value, (gdouble) list->data.v_double); break; case G_TYPE_STRING: g_value_set_string (value, (gchar *) list->data.v_pointer); break; case G_TYPE_POINTER: g_value_set_pointer (value, (gpointer) list->data.v_pointer); break; case G_TYPE_BOXED: g_value_set_boxed (value, (gpointer) list->data.v_pointer); break; case G_TYPE_OBJECT: g_value_set_object (value, (GObject *) list->data.v_pointer); break; default: g_warning ("%s: Unsupported type (%s) retrieved.", G_STRLOC, g_type_name (value->g_type)); break; } } void _foo_tree_data_list_value_to_node (FooTreeDataList *list, GValue *value) { switch (get_fundamental_type (G_VALUE_TYPE (value))) { case G_TYPE_BOOLEAN: list->data.v_int = g_value_get_boolean (value); break; case G_TYPE_CHAR: list->data.v_char = g_value_get_char (value); break; case G_TYPE_UCHAR: list->data.v_uchar = g_value_get_uchar (value); break; case G_TYPE_INT: list->data.v_int = g_value_get_int (value); break; case G_TYPE_UINT: list->data.v_uint = g_value_get_uint (value); break; case G_TYPE_LONG: list->data.v_long = g_value_get_long (value); break; case G_TYPE_ULONG: list->data.v_ulong = g_value_get_ulong (value); break; case G_TYPE_INT64: list->data.v_int64 = g_value_get_int64 (value); break; case G_TYPE_UINT64: list->data.v_uint64 = g_value_get_uint64 (value); break; case G_TYPE_ENUM: list->data.v_int = g_value_get_enum (value); break; case G_TYPE_FLAGS: list->data.v_uint = g_value_get_flags (value); break; case G_TYPE_POINTER: list->data.v_pointer = g_value_get_pointer (value); break; case G_TYPE_FLOAT: list->data.v_float = g_value_get_float (value); break; case G_TYPE_DOUBLE: list->data.v_double = g_value_get_double (value); break; case G_TYPE_STRING: g_free (list->data.v_pointer); list->data.v_pointer = g_value_dup_string (value); break; case G_TYPE_OBJECT: if (list->data.v_pointer) g_object_unref (list->data.v_pointer); list->data.v_pointer = g_value_dup_object (value); break; case G_TYPE_BOXED: if (list->data.v_pointer) g_boxed_free (G_VALUE_TYPE (value), list->data.v_pointer); list->data.v_pointer = g_value_dup_boxed (value); break; default: g_warning ("%s: Unsupported type (%s) stored.", G_STRLOC, g_type_name (G_VALUE_TYPE (value))); break; } } FooTreeDataList * _foo_tree_data_list_node_copy (FooTreeDataList *list, GType type) { FooTreeDataList *new_list; g_return_val_if_fail (list != NULL, NULL); new_list = _foo_tree_data_list_alloc (); new_list->next = NULL; switch (get_fundamental_type (type)) { case G_TYPE_BOOLEAN: case G_TYPE_CHAR: case G_TYPE_UCHAR: case G_TYPE_INT: case G_TYPE_UINT: case G_TYPE_LONG: case G_TYPE_ULONG: case G_TYPE_INT64: case G_TYPE_UINT64: case G_TYPE_ENUM: case G_TYPE_FLAGS: case G_TYPE_POINTER: case G_TYPE_FLOAT: case G_TYPE_DOUBLE: new_list->data = list->data; break; case G_TYPE_STRING: new_list->data.v_pointer = g_strdup (list->data.v_pointer); break; case G_TYPE_OBJECT: case G_TYPE_INTERFACE: new_list->data.v_pointer = list->data.v_pointer; if (new_list->data.v_pointer) g_object_ref (new_list->data.v_pointer); break; case G_TYPE_BOXED: if (list->data.v_pointer) new_list->data.v_pointer = g_boxed_copy (type, list->data.v_pointer); else new_list->data.v_pointer = NULL; break; default: g_warning ("Unsupported node type (%s) copied.", g_type_name (type)); break; } return new_list; } gint _foo_tree_data_list_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) { gint column = GPOINTER_TO_INT (user_data); GType type = gtk_tree_model_get_column_type (model, column); GValue a_value = {0, }; GValue b_value = {0, }; gint retval; const gchar *stra, *strb; gtk_tree_model_get_value (model, a, column, &a_value); gtk_tree_model_get_value (model, b, column, &b_value); switch (get_fundamental_type (type)) { case G_TYPE_BOOLEAN: if (g_value_get_boolean (&a_value) < g_value_get_boolean (&b_value)) retval = -1; else if (g_value_get_boolean (&a_value) == g_value_get_boolean (&b_value)) retval = 0; else retval = 1; break; case G_TYPE_CHAR: if (g_value_get_char (&a_value) < g_value_get_char (&b_value)) retval = -1; else if (g_value_get_char (&a_value) == g_value_get_char (&b_value)) retval = 0; else retval = 1; break; case G_TYPE_UCHAR: if (g_value_get_uchar (&a_value) < g_value_get_uchar (&b_value)) retval = -1; else if (g_value_get_uchar (&a_value) == g_value_get_uchar (&b_value)) retval = 0; else retval = 1; break; case G_TYPE_INT: if (g_value_get_int (&a_value) < g_value_get_int (&b_value)) retval = -1; else if (g_value_get_int (&a_value) == g_value_get_int (&b_value)) retval = 0; else retval = 1; break; case G_TYPE_UINT: if (g_value_get_uint (&a_value) < g_value_get_uint (&b_value)) retval = -1; else if (g_value_get_uint (&a_value) == g_value_get_uint (&b_value)) retval = 0; else retval = 1; break; case G_TYPE_LONG: if (g_value_get_long (&a_value) < g_value_get_long (&b_value)) retval = -1; else if (g_value_get_long (&a_value) == g_value_get_long (&b_value)) retval = 0; else retval = 1; break; case G_TYPE_ULONG: if (g_value_get_ulong (&a_value) < g_value_get_ulong (&b_value)) retval = -1; else if (g_value_get_ulong (&a_value) == g_value_get_ulong (&b_value)) retval = 0; else retval = 1; break; case G_TYPE_INT64: if (g_value_get_int64 (&a_value) < g_value_get_int64 (&b_value)) retval = -1; else if (g_value_get_int64 (&a_value) == g_value_get_int64 (&b_value)) retval = 0; else retval = 1; break; case G_TYPE_UINT64: if (g_value_get_uint64 (&a_value) < g_value_get_uint64 (&b_value)) retval = -1; else if (g_value_get_uint64 (&a_value) == g_value_get_uint64 (&b_value)) retval = 0; else retval = 1; break; case G_TYPE_ENUM: /* this is somewhat bogus. */ if (g_value_get_enum (&a_value) < g_value_get_enum (&b_value)) retval = -1; else if (g_value_get_enum (&a_value) == g_value_get_enum (&b_value)) retval = 0; else retval = 1; break; case G_TYPE_FLAGS: /* this is even more bogus. */ if (g_value_get_flags (&a_value) < g_value_get_flags (&b_value)) retval = -1; else if (g_value_get_flags (&a_value) == g_value_get_flags (&b_value)) retval = 0; else retval = 1; break; case G_TYPE_FLOAT: if (g_value_get_float (&a_value) < g_value_get_float (&b_value)) retval = -1; else if (g_value_get_float (&a_value) == g_value_get_float (&b_value)) retval = 0; else retval = 1; break; case G_TYPE_DOUBLE: if (g_value_get_double (&a_value) < g_value_get_double (&b_value)) retval = -1; else if (g_value_get_double (&a_value) == g_value_get_double (&b_value)) retval = 0; else retval = 1; break; case G_TYPE_STRING: stra = g_value_get_string (&a_value); strb = g_value_get_string (&b_value); if (stra == NULL) stra = ""; if (strb == NULL) strb = ""; retval = g_utf8_collate (stra, strb); break; case G_TYPE_POINTER: case G_TYPE_BOXED: case G_TYPE_OBJECT: default: g_warning ("Attempting to sort on invalid type %s\n", g_type_name (type)); retval = FALSE; break; } g_value_unset (&a_value); g_value_unset (&b_value); return retval; } GList * _foo_tree_data_list_header_new (gint n_columns, GType *types) { GList *retval = NULL; gint i; for (i = 0; i < n_columns; i ++) { GtkTreeDataSortHeader *header; header = g_slice_new (GtkTreeDataSortHeader); retval = g_list_prepend (retval, header); header->sort_column_id = i; header->func = _foo_tree_data_list_compare_func; header->destroy = NULL; header->data = GINT_TO_POINTER (i); } return g_list_reverse (retval); } void _foo_tree_data_list_header_free (GList *list) { GList *tmp; for (tmp = list; tmp; tmp = tmp->next) { GtkTreeDataSortHeader *header = (GtkTreeDataSortHeader *) tmp->data; if (header->destroy) { GDestroyNotify d = header->destroy; header->destroy = NULL; d (header->data); } g_slice_free (GtkTreeDataSortHeader, header); } g_list_free (list); } GtkTreeDataSortHeader * _foo_tree_data_list_get_header (GList *header_list, gint sort_column_id) { GtkTreeDataSortHeader *header = NULL; for (; header_list; header_list = header_list->next) { header = (GtkTreeDataSortHeader*) header_list->data; if (header->sort_column_id == sort_column_id) return header; } return NULL; } GList * _foo_tree_data_list_set_header (GList *header_list, gint sort_column_id, GtkTreeIterCompareFunc func, gpointer data, GDestroyNotify destroy) { GList *list = header_list; GtkTreeDataSortHeader *header = NULL; for (; list; list = list->next) { header = (GtkTreeDataSortHeader*) list->data; if (header->sort_column_id == sort_column_id) break; header = NULL; if (list->next == NULL) break; } if (header == NULL) { header = g_slice_new0 (GtkTreeDataSortHeader); header->sort_column_id = sort_column_id; if (list) list = g_list_append (list, header); else header_list = g_list_append (header_list, header); } if (header->destroy) { GDestroyNotify d = header->destroy; header->destroy = NULL; d (header->data); } header->func = func; header->data = data; header->destroy = destroy; return header_list; } sysprof-1.2.0/tracker.h0000644000175000017500000000142212021176713011743 00000000000000#include #include "profile.h" typedef struct tracker_t tracker_t; tracker_t *tracker_new (void); void tracker_free (tracker_t *); void tracker_add_process (tracker_t *tracker, pid_t pid, const char *command_line); void tracker_add_fork (tracker_t *tracker, pid_t pid, pid_t child_pid); void tracker_add_exit (tracker_t *tracker, pid_t pid); void tracker_add_map (tracker_t * tracker, pid_t pid, uint64_t start, uint64_t end, uint64_t offset, uint64_t inode, const char *filename); void tracker_add_sample (tracker_t *tracker, pid_t pid, uint64_t *ips, int n_ips); Profile *tracker_create_profile (tracker_t *tracker); sysprof-1.2.0/testunwind.c0000644000175000017500000000052312021176713012510 00000000000000#include "elfparser.h" #include "unwind.h" int main (int argc, char **argv) { const guchar *data; ElfParser *elf; if (argc == 1) { g_print ("no arg\n"); return -1; } elf = elf_parser_new (argv[1], NULL); if (!elf) { g_print ("NO ELF!!!!\n"); return -1; } unwind (elf); return 0; } sysprof-1.2.0/treeviewutils.h0000644000175000017500000000371512021176713013232 00000000000000/* -*- mode: C; c-file-style: "linux" -*- */ /* MemProf -- memory profiler and leak detector * Copyright 2002, Soeren Sandmann (sandmann@daimi.au.dk) * Copyright 2003, 2004, Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*====*/ #include GtkTreeViewColumn *add_plain_text_column (GtkTreeView *view, const char *title, gint model_column); GtkTreeViewColumn *add_double_format_column (GtkTreeView *view, const char *title, int model_column, const char *format); GtkTreeViewColumn *add_pointer_column (GtkTreeView *view, const char *title, int model_column); void tree_view_set_model_with_default_sort (GtkTreeView *view, GtkTreeModel *model, int model_column, GtkSortType default_sort); void tree_view_set_sort_column (GtkTreeView *view, int model_column, int sort_type); typedef void (* VisibleCallback) (GtkTreeView *view, GtkTreePath *path, GtkTreeIter *iter, gpointer data); void tree_view_foreach_visible (GtkTreeView *view, VisibleCallback callback, gpointer data); void set_error_va (GError **err, gint domain, gint code, const char *format, va_list args); sysprof-1.2.0/config.h.in0000644000175000017500000000130612022706430012157 00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ /* Look for global separate debug info in this path */ #undef DEBUGDIR /* Define to 1 if your C compiler doesn't accept -c and -o together. */ #undef NO_MINUS_C_MINUS_O /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION sysprof-1.2.0/demangle.c0000644000175000017500000074312312021176713012072 00000000000000/* * This file is a concatenation of the files * * cp-demangle.c * cp-dmeangle.h * cplus-dem.c * demangle.h * * all taken from libiberty in binutils v. 2.16. After this concatenation * many calls to other functions in libiberty were replaced by calls to * similar functions in glib. Also global entry points that we don't need * in sysprof were made static or removed. * * Let's hope that no bugs are ever found in this file! * * Maybe someday look at what can be deleted from this file * * - "mini string library" can be replaced with GString * - "option" parameter to cplus_demangle can be deleted * - demangling is always "auto" */ /* Copyright notices: * * Demangler for g++ V3 ABI. * Copyright (C) 2003, 2004 Free Software Foundation, Inc. * Written by Ian Lance Taylor . * * This file is part of the libiberty library, which is part of GCC. Defs for interface to demanglers. Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Internal demangler interface for g++ V3 ABI. Copyright (C) 2003, 2004 Free Software Foundation, Inc. Written by Ian Lance Taylor . Demangler for GNU C++ Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.uucp) Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling Modified by Satish Pai (pai@apollo.hp.com) for HP demangling This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This code implements a demangler for the g++ V3 ABI. The ABI is described on this web page: http://www.codesourcery.com/cxx-abi/abi.html#mangling This code was written while looking at the demangler written by Alex Samuel . This code first pulls the mangled name apart into a list of components, and then walks the list generating the demangled name. This file will normally define the following functions, q.v.: char *cplus_demangle_v3(const char *mangled, int options) char *java_demangle_v3(const char *mangled) enum gnu_v3_ctor_kinds is_gnu_v3_mangled_ctor (const char *name) enum gnu_v3_dtor_kinds is_gnu_v3_mangled_dtor (const char *name) Also, the interface to the component list is public, and defined in demangle.h. The interface consists of these types, which are defined in demangle.h: enum demangle_component_type struct demangle_component and these functions defined in this file: cplus_demangle_fill_name cplus_demangle_fill_extended_operator cplus_demangle_fill_ctor cplus_demangle_fill_dtor cplus_demangle_print and other functions defined in the file cp-demint.c. This file also defines some other functions and variables which are only to be used by the file cp-demint.c. Preprocessor macros you can define while compiling this file: IN_LIBGCC2 If defined, this file defines the following function, q.v.: char *__cxa_demangle (const char *mangled, char *buf, size_t *len, int *status) instead of cplus_demangle_v3() and java_demangle_v3(). IN_GLIBCPP_V3 If defined, this file defines only __cxa_demangle(), and no other publically visible functions or variables. CP_DEMANGLE_DEBUG If defined, turns on debugging mode, which prints information on stdout about the mangled string. This is not generally useful. */ #include #include #include #include #include /* Defs for interface to demanglers. Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if !defined (DEMANGLE_H) #define DEMANGLE_H #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* Options passed to cplus_demangle (in 2nd parameter). */ #define DMGL_NO_OPTS 0 /* For readability... */ #define DMGL_PARAMS (1 << 0) /* Include function args */ #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ #define DMGL_JAVA (1 << 2) /* Demangle as Java rather than C++. */ #define DMGL_VERBOSE (1 << 3) /* Include implementation details. */ #define DMGL_TYPES (1 << 4) /* Also try to demangle type encodings. */ #define DMGL_AUTO (1 << 8) #define DMGL_GNU (1 << 9) #define DMGL_LUCID (1 << 10) #define DMGL_ARM (1 << 11) #define DMGL_HP (1 << 12) /* For the HP aCC compiler; same as ARM except for template arguments, etc. */ #define DMGL_EDG (1 << 13) #define DMGL_GNU_V3 (1 << 14) #define DMGL_GNAT (1 << 15) /* If none of these are set, use 'current_demangling_style' as the default. */ #define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT) /* Enumeration of possible demangling styles. Lucid and ARM styles are still kept logically distinct, even though they now both behave identically. The resulting style is actual the union of both. I.E. either style recognizes both "__pt__" and "__rf__" for operator "->", even though the first is lucid style and the second is ARM style. (FIXME?) */ enum demangling_styles { no_demangling = -1, unknown_demangling = 0, auto_demangling = DMGL_AUTO, gnu_demangling = DMGL_GNU, lucid_demangling = DMGL_LUCID, arm_demangling = DMGL_ARM, hp_demangling = DMGL_HP, edg_demangling = DMGL_EDG, gnu_v3_demangling = DMGL_GNU_V3, java_demangling = DMGL_JAVA, gnat_demangling = DMGL_GNAT }; /* Define string names for the various demangling styles. */ #define NO_DEMANGLING_STYLE_STRING "none" #define AUTO_DEMANGLING_STYLE_STRING "auto" #define GNU_DEMANGLING_STYLE_STRING "gnu" #define LUCID_DEMANGLING_STYLE_STRING "lucid" #define ARM_DEMANGLING_STYLE_STRING "arm" #define HP_DEMANGLING_STYLE_STRING "hp" #define EDG_DEMANGLING_STYLE_STRING "edg" #define GNU_V3_DEMANGLING_STYLE_STRING "gnu-v3" #define JAVA_DEMANGLING_STYLE_STRING "java" #define GNAT_DEMANGLING_STYLE_STRING "gnat" /* Some macros to test what demangling style is active. */ #define CURRENT_DEMANGLING_STYLE current_demangling_style #define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO) #define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU) #define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID) #define ARM_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_ARM) #define HP_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_HP) #define EDG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_EDG) #define GNU_V3_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_V3) #define JAVA_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_JAVA) #define GNAT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNAT) /* Provide information about the available demangle styles. This code is pulled from gdb into libiberty because it is useful to binutils also. */ #define PARAMS(a) a #define ATTRIBUTE_NORETURN G_GNUC_NORETURN #define ATTRIBUTE_UNUSED G_GNUC_UNUSED static const struct demangler_engine { const char *const demangling_style_name; const enum demangling_styles demangling_style; const char *const demangling_style_doc; } libiberty_demanglers[]; #if 0 extern char * cplus_demangle PARAMS ((const char *mangled, int options)); #endif #if 0 extern int cplus_demangle_opname PARAMS ((const char *opname, char *result, int options)); extern const char * cplus_mangle_opname PARAMS ((const char *opname, int options)); #endif /* Note: This sets global state. FIXME if you care about multi-threading. */ enum gnu_v3_ctor_kinds { gnu_v3_complete_object_ctor = 1, gnu_v3_base_object_ctor, gnu_v3_complete_object_allocating_ctor }; /* Return non-zero iff NAME is the mangled form of a constructor name in the G++ V3 ABI demangling style. Specifically, return an `enum gnu_v3_ctor_kinds' value indicating what kind of constructor it is. */ extern enum gnu_v3_ctor_kinds is_gnu_v3_mangled_ctor PARAMS ((const char *name)); enum gnu_v3_dtor_kinds { gnu_v3_deleting_dtor = 1, gnu_v3_complete_object_dtor, gnu_v3_base_object_dtor }; /* Return non-zero iff NAME is the mangled form of a destructor name in the G++ V3 ABI demangling style. Specifically, return an `enum gnu_v3_dtor_kinds' value, indicating what kind of destructor it is. */ extern enum gnu_v3_dtor_kinds is_gnu_v3_mangled_dtor PARAMS ((const char *name)); /* The V3 demangler works in two passes. The first pass builds a tree representation of the mangled name, and the second pass turns the tree representation into a demangled string. Here we define an interface to permit a caller to build their own tree representation, which they can pass to the demangler to get a demangled string. This can be used to canonicalize user input into something which the demangler might output. It could also be used by other demanglers in the future. */ /* These are the component types which may be found in the tree. Many component types have one or two subtrees, referred to as left and right (a component type with only one subtree puts it in the left subtree). */ enum demangle_component_type { /* A name, with a length and a pointer to a string. */ DEMANGLE_COMPONENT_NAME, /* A qualified name. The left subtree is a class or namespace or some such thing, and the right subtree is a name qualified by that class. */ DEMANGLE_COMPONENT_QUAL_NAME, /* A local name. The left subtree describes a function, and the right subtree is a name which is local to that function. */ DEMANGLE_COMPONENT_LOCAL_NAME, /* A typed name. The left subtree is a name, and the right subtree describes that name as a function. */ DEMANGLE_COMPONENT_TYPED_NAME, /* A template. The left subtree is a template name, and the right subtree is a template argument list. */ DEMANGLE_COMPONENT_TEMPLATE, /* A template parameter. This holds a number, which is the template parameter index. */ DEMANGLE_COMPONENT_TEMPLATE_PARAM, /* A constructor. This holds a name and the kind of constructor. */ DEMANGLE_COMPONENT_CTOR, /* A destructor. This holds a name and the kind of destructor. */ DEMANGLE_COMPONENT_DTOR, /* A vtable. This has one subtree, the type for which this is a vtable. */ DEMANGLE_COMPONENT_VTABLE, /* A VTT structure. This has one subtree, the type for which this is a VTT. */ DEMANGLE_COMPONENT_VTT, /* A construction vtable. The left subtree is the type for which this is a vtable, and the right subtree is the derived type for which this vtable is built. */ DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, /* A typeinfo structure. This has one subtree, the type for which this is the tpeinfo structure. */ DEMANGLE_COMPONENT_TYPEINFO, /* A typeinfo name. This has one subtree, the type for which this is the typeinfo name. */ DEMANGLE_COMPONENT_TYPEINFO_NAME, /* A typeinfo function. This has one subtree, the type for which this is the tpyeinfo function. */ DEMANGLE_COMPONENT_TYPEINFO_FN, /* A thunk. This has one subtree, the name for which this is a thunk. */ DEMANGLE_COMPONENT_THUNK, /* A virtual thunk. This has one subtree, the name for which this is a virtual thunk. */ DEMANGLE_COMPONENT_VIRTUAL_THUNK, /* A covariant thunk. This has one subtree, the name for which this is a covariant thunk. */ DEMANGLE_COMPONENT_COVARIANT_THUNK, /* A Java class. This has one subtree, the type. */ DEMANGLE_COMPONENT_JAVA_CLASS, /* A guard variable. This has one subtree, the name for which this is a guard variable. */ DEMANGLE_COMPONENT_GUARD, /* A reference temporary. This has one subtree, the name for which this is a temporary. */ DEMANGLE_COMPONENT_REFTEMP, /* A standard substitution. This holds the name of the substitution. */ DEMANGLE_COMPONENT_SUB_STD, /* The restrict qualifier. The one subtree is the type which is being qualified. */ DEMANGLE_COMPONENT_RESTRICT, /* The volatile qualifier. The one subtree is the type which is being qualified. */ DEMANGLE_COMPONENT_VOLATILE, /* The const qualifier. The one subtree is the type which is being qualified. */ DEMANGLE_COMPONENT_CONST, /* The restrict qualifier modifying a member function. The one subtree is the type which is being qualified. */ DEMANGLE_COMPONENT_RESTRICT_THIS, /* The volatile qualifier modifying a member function. The one subtree is the type which is being qualified. */ DEMANGLE_COMPONENT_VOLATILE_THIS, /* The const qualifier modifying a member function. The one subtree is the type which is being qualified. */ DEMANGLE_COMPONENT_CONST_THIS, /* A vendor qualifier. The left subtree is the type which is being qualified, and the right subtree is the name of the qualifier. */ DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL, /* A pointer. The one subtree is the type which is being pointed to. */ DEMANGLE_COMPONENT_POINTER, /* A reference. The one subtree is the type which is being referenced. */ DEMANGLE_COMPONENT_REFERENCE, /* A complex type. The one subtree is the base type. */ DEMANGLE_COMPONENT_COMPLEX, /* An imaginary type. The one subtree is the base type. */ DEMANGLE_COMPONENT_IMAGINARY, /* A builtin type. This holds the builtin type information. */ DEMANGLE_COMPONENT_BUILTIN_TYPE, /* A vendor's builtin type. This holds the name of the type. */ DEMANGLE_COMPONENT_VENDOR_TYPE, /* A function type. The left subtree is the return type. The right subtree is a list of ARGLIST nodes. Either or both may be NULL. */ DEMANGLE_COMPONENT_FUNCTION_TYPE, /* An array type. The left subtree is the dimension, which may be NULL, or a string (represented as DEMANGLE_COMPONENT_NAME), or an expression. The right subtree is the element type. */ DEMANGLE_COMPONENT_ARRAY_TYPE, /* A pointer to member type. The left subtree is the class type, and the right subtree is the member type. CV-qualifiers appear on the latter. */ DEMANGLE_COMPONENT_PTRMEM_TYPE, /* An argument list. The left subtree is the current argument, and the right subtree is either NULL or another ARGLIST node. */ DEMANGLE_COMPONENT_ARGLIST, /* A template argument list. The left subtree is the current template argument, and the right subtree is either NULL or another TEMPLATE_ARGLIST node. */ DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, /* An operator. This holds information about a standard operator. */ DEMANGLE_COMPONENT_OPERATOR, /* An extended operator. This holds the number of arguments, and the name of the extended operator. */ DEMANGLE_COMPONENT_EXTENDED_OPERATOR, /* A typecast, represented as a unary operator. The one subtree is the type to which the argument should be cast. */ DEMANGLE_COMPONENT_CAST, /* A unary expression. The left subtree is the operator, and the right subtree is the single argument. */ DEMANGLE_COMPONENT_UNARY, /* A binary expression. The left subtree is the operator, and the right subtree is a BINARY_ARGS. */ DEMANGLE_COMPONENT_BINARY, /* Arguments to a binary expression. The left subtree is the first argument, and the right subtree is the second argument. */ DEMANGLE_COMPONENT_BINARY_ARGS, /* A trinary expression. The left subtree is the operator, and the right subtree is a TRINARY_ARG1. */ DEMANGLE_COMPONENT_TRINARY, /* Arguments to a trinary expression. The left subtree is the first argument, and the right subtree is a TRINARY_ARG2. */ DEMANGLE_COMPONENT_TRINARY_ARG1, /* More arguments to a trinary expression. The left subtree is the second argument, and the right subtree is the third argument. */ DEMANGLE_COMPONENT_TRINARY_ARG2, /* A literal. The left subtree is the type, and the right subtree is the value, represented as a DEMANGLE_COMPONENT_NAME. */ DEMANGLE_COMPONENT_LITERAL, /* A negative literal. Like LITERAL, but the value is negated. This is a minor hack: the NAME used for LITERAL points directly to the mangled string, but since negative numbers are mangled using 'n' instead of '-', we want a way to indicate a negative number which involves neither modifying the mangled string nor allocating a new copy of the literal in memory. */ DEMANGLE_COMPONENT_LITERAL_NEG }; /* Types which are only used internally. */ struct demangle_operator_info; struct demangle_builtin_type_info; /* A node in the tree representation is an instance of a struct demangle_component. Note that the field names of the struct are not well protected against macros defined by the file including this one. We can fix this if it ever becomes a problem. */ struct demangle_component { /* The type of this component. */ enum demangle_component_type type; union { /* For DEMANGLE_COMPONENT_NAME. */ struct { /* A pointer to the name (which need not NULL terminated) and its length. */ const char *s; int len; } s_name; /* For DEMANGLE_COMPONENT_OPERATOR. */ struct { /* Operator. */ const struct demangle_operator_info *op; } s_operator; /* For DEMANGLE_COMPONENT_EXTENDED_OPERATOR. */ struct { /* Number of arguments. */ int args; /* Name. */ struct demangle_component *name; } s_extended_operator; /* For DEMANGLE_COMPONENT_CTOR. */ struct { /* Kind of constructor. */ enum gnu_v3_ctor_kinds kind; /* Name. */ struct demangle_component *name; } s_ctor; /* For DEMANGLE_COMPONENT_DTOR. */ struct { /* Kind of destructor. */ enum gnu_v3_dtor_kinds kind; /* Name. */ struct demangle_component *name; } s_dtor; /* For DEMANGLE_COMPONENT_BUILTIN_TYPE. */ struct { /* Builtin type. */ const struct demangle_builtin_type_info *type; } s_builtin; /* For DEMANGLE_COMPONENT_SUB_STD. */ struct { /* Standard substitution string. */ const char* string; /* Length of string. */ int len; } s_string; /* For DEMANGLE_COMPONENT_TEMPLATE_PARAM. */ struct { /* Template parameter index. */ long number; } s_number; /* For other types. */ struct { /* Left (or only) subtree. */ struct demangle_component *left; /* Right subtree. */ struct demangle_component *right; } s_binary; } u; }; /* People building mangled trees are expected to allocate instances of struct demangle_component themselves. They can then call one of the following functions to fill them in. */ /* Fill in most component types with a left subtree and a right subtree. Returns non-zero on success, zero on failure, such as an unrecognized or inappropriate component type. */ extern int cplus_demangle_fill_component PARAMS ((struct demangle_component *fill, enum demangle_component_type, struct demangle_component *left, struct demangle_component *right)); /* Fill in a DEMANGLE_COMPONENT_NAME. Returns non-zero on success, zero for bad arguments. */ extern int cplus_demangle_fill_name PARAMS ((struct demangle_component *fill, const char *, int)); /* Fill in a DEMANGLE_COMPONENT_BUILTIN_TYPE, using the name of the builtin type (e.g., "int", etc.). Returns non-zero on success, zero if the type is not recognized. */ extern int cplus_demangle_fill_builtin_type PARAMS ((struct demangle_component *fill, const char *type_name)); /* Fill in a DEMANGLE_COMPONENT_OPERATOR, using the name of the operator and the number of arguments which it takes (the latter is used to disambiguate operators which can be both binary and unary, such as '-'). Returns non-zero on success, zero if the operator is not recognized. */ extern int cplus_demangle_fill_operator PARAMS ((struct demangle_component *fill, const char *opname, int args)); /* Fill in a DEMANGLE_COMPONENT_EXTENDED_OPERATOR, providing the number of arguments and the name. Returns non-zero on success, zero for bad arguments. */ extern int cplus_demangle_fill_extended_operator PARAMS ((struct demangle_component *fill, int numargs, struct demangle_component *nm)); /* Fill in a DEMANGLE_COMPONENT_CTOR. Returns non-zero on success, zero for bad arguments. */ extern int cplus_demangle_fill_ctor PARAMS ((struct demangle_component *fill, enum gnu_v3_ctor_kinds kind, struct demangle_component *name)); /* Fill in a DEMANGLE_COMPONENT_DTOR. Returns non-zero on success, zero for bad arguments. */ extern int cplus_demangle_fill_dtor PARAMS ((struct demangle_component *fill, enum gnu_v3_dtor_kinds kind, struct demangle_component *name)); /* This function translates a mangled name into a struct demangle_component tree. The first argument is the mangled name. The second argument is DMGL_* options. This returns a pointer to a tree on success, or NULL on failure. On success, the third argument is set to a block of memory allocated by malloc. This block should be passed to free when the tree is no longer needed. */ extern struct demangle_component * cplus_demangle_v3_components PARAMS ((const char *mangled, int options, void **mem)); /* This function takes a struct demangle_component tree and returns the corresponding demangled string. The first argument is DMGL_* options. The second is the tree to demangle. The third is a guess at the length of the demangled string, used to initially allocate the return buffer. The fourth is a pointer to a size_t. On success, this function returns a buffer allocated by malloc(), and sets the size_t pointed to by the fourth argument to the size of the allocated buffer (not the length of the returned string). On failure, this function returns NULL, and sets the size_t pointed to by the fourth argument to 0 for an invalid tree, or to 1 for a memory allocation error. */ extern char * cplus_demangle_print PARAMS ((int options, const struct demangle_component *tree, int estimated_length, size_t *p_allocated_size)); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* DEMANGLE_H */ /* V3 ABI demangling entry points, defined in cp-demangle.c. */ static char* cplus_demangle_v3 PARAMS ((const char* mangled, int options)); static char* java_demangle_v3 PARAMS ((const char* mangled)); /* Internal demangler interface for g++ V3 ABI. Copyright (C) 2003, 2004 Free Software Foundation, Inc. Written by Ian Lance Taylor . This file is part of the libiberty library, which is part of GCC. This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. In addition to the permissions in the GNU General Public License, the Free Software Foundation gives you unlimited permission to link the compiled version of this file into combinations with other programs, and to distribute those combinations without any restriction coming from the use of this file. (The General Public License restrictions do apply in other respects; for example, they cover modification of the file, and distribution when not linked into a combined executable.) This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file provides some definitions shared by cp-demangle.c and cp-demint.c. It should not be included by any other files. */ /* Information we keep for operators. */ struct demangle_operator_info { /* Mangled name. */ const char *code; /* Real name. */ const char *name; /* Length of real name. */ int len; /* Number of arguments. */ int args; }; /* How to print the value of a builtin type. */ enum d_builtin_type_print { /* Print as (type)val. */ D_PRINT_DEFAULT, /* Print as integer. */ D_PRINT_INT, /* Print as unsigned integer, with trailing "u". */ D_PRINT_UNSIGNED, /* Print as long, with trailing "l". */ D_PRINT_LONG, /* Print as unsigned long, with trailing "ul". */ D_PRINT_UNSIGNED_LONG, /* Print as long long, with trailing "ll". */ D_PRINT_LONG_LONG, /* Print as unsigned long long, with trailing "ull". */ D_PRINT_UNSIGNED_LONG_LONG, /* Print as bool. */ D_PRINT_BOOL, /* Print as float--put value in square brackets. */ D_PRINT_FLOAT, /* Print in usual way, but here to detect void. */ D_PRINT_VOID }; /* Information we keep for a builtin type. */ struct demangle_builtin_type_info { /* Type name. */ const char *name; /* Length of type name. */ int len; /* Type name when using Java. */ const char *java_name; /* Length of java name. */ int java_len; /* How to print a value of this type. */ enum d_builtin_type_print print; }; /* The information structure we pass around. */ struct d_info { /* The string we are demangling. */ const char *s; /* The end of the string we are demangling. */ const char *send; /* The options passed to the demangler. */ int options; /* The next character in the string to consider. */ const char *n; /* The array of components. */ struct demangle_component *comps; /* The index of the next available component. */ int next_comp; /* The number of available component structures. */ int num_comps; /* The array of substitutions. */ struct demangle_component **subs; /* The index of the next substitution. */ int next_sub; /* The number of available entries in the subs array. */ int num_subs; /* The number of substitutions which we actually made from the subs array, plus the number of template parameter references we saw. */ int did_subs; /* The last name we saw, for constructors and destructors. */ struct demangle_component *last_name; /* A running total of the length of large expansions from the mangled name to the demangled name, such as standard substitutions and builtin types. */ int expansion; }; #define d_peek_char(di) (*((di)->n)) #define d_peek_next_char(di) ((di)->n[1]) #define d_advance(di, i) ((di)->n += (i)) #define d_next_char(di) (*((di)->n++)) #define d_str(di) ((di)->n) /* Functions and arrays in cp-demangle.c which are referenced by functions in cp-demint.c. */ #define CP_STATIC_IF_GLIBCPP_V3 static #define D_BUILTIN_TYPE_COUNT (26) #if 0 static struct demangle_component * cplus_demangle_mangled_name PARAMS ((struct d_info *, int)); #endif #if 0 static struct demangle_component * cplus_demangle_type PARAMS ((struct d_info *)); #endif extern void cplus_demangle_init_info PARAMS ((const char *, int, size_t, struct d_info *)); #if 0 /* cp-demangle.c needs to define this a little differently */ #undef CP_STATIC_IF_GLIBCPP_V3 #endif #define IN_GLIBCPP_V3 /* If IN_GLIBCPP_V3 is defined, some functions are made static. We also rename them via #define to avoid compiler errors when the static definition conflicts with the extern declaration in a header file. */ #ifdef IN_GLIBCPP_V3 #define CP_STATIC_IF_GLIBCPP_V3 static #define cplus_demangle_fill_name d_fill_name static int d_fill_name PARAMS ((struct demangle_component *, const char *, int)); #define cplus_demangle_fill_extended_operator d_fill_extended_operator static int d_fill_extended_operator PARAMS ((struct demangle_component *, int, struct demangle_component *)); #define cplus_demangle_fill_ctor d_fill_ctor static int d_fill_ctor PARAMS ((struct demangle_component *, enum gnu_v3_ctor_kinds, struct demangle_component *)); #define cplus_demangle_fill_dtor d_fill_dtor static int d_fill_dtor PARAMS ((struct demangle_component *, enum gnu_v3_dtor_kinds, struct demangle_component *)); #define cplus_demangle_mangled_name d_mangled_name static struct demangle_component * d_mangled_name PARAMS ((struct d_info *, int)); #define cplus_demangle_type d_type static struct demangle_component * d_type PARAMS ((struct d_info *)); #define cplus_demangle_print d_print static char * d_print PARAMS ((int, const struct demangle_component *, int, size_t *)); #define cplus_demangle_init_info d_init_info static void d_init_info PARAMS ((const char *, int, size_t, struct d_info *)); #else /* ! defined(IN_GLIBCPP_V3) */ #define CP_STATIC_IF_GLIBCPP_V3 #endif /* ! defined(IN_GLIBCPP_V3) */ /* See if the compiler supports dynamic arrays. */ #ifdef __GNUC__ #define CP_DYNAMIC_ARRAYS #else #ifdef __STDC__ #ifdef __STDC_VERSION__ #if __STDC_VERSION__ >= 199901L #define CP_DYNAMIC_ARRAYS #endif /* __STDC__VERSION >= 199901L */ #endif /* defined (__STDC_VERSION__) */ #endif /* defined (__STDC__) */ #endif /* ! defined (__GNUC__) */ /* We avoid pulling in the ctype tables, to prevent pulling in additional unresolved symbols when this code is used in a library. FIXME: Is this really a valid reason? This comes from the original V3 demangler code. As of this writing this file has the following undefined references when compiled with -DIN_GLIBCPP_V3: malloc, realloc, free, memcpy, strcpy, strcat, strlen. */ #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') #define IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z') #define IS_LOWER(c) ((c) >= 'a' && (c) <= 'z') /* The prefix prepended by GCC to an identifier represnting the anonymous namespace. */ #define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_" #define ANONYMOUS_NAMESPACE_PREFIX_LEN \ (sizeof (ANONYMOUS_NAMESPACE_PREFIX) - 1) /* Information we keep for the standard substitutions. */ struct d_standard_sub_info { /* The code for this substitution. */ char code; /* The simple string it expands to. */ const char *simple_expansion; /* The length of the simple expansion. */ int simple_len; /* The results of a full, verbose, expansion. This is used when qualifying a constructor/destructor, or when in verbose mode. */ const char *full_expansion; /* The length of the full expansion. */ int full_len; /* What to set the last_name field of d_info to; NULL if we should not set it. This is only relevant when qualifying a constructor/destructor. */ const char *set_last_name; /* The length of set_last_name. */ int set_last_name_len; }; /* Accessors for subtrees of struct demangle_component. */ #define d_left(dc) ((dc)->u.s_binary.left) #define d_right(dc) ((dc)->u.s_binary.right) /* A list of templates. This is used while printing. */ struct d_print_template { /* Next template on the list. */ struct d_print_template *next; /* This template. */ const struct demangle_component *template; }; /* A list of type modifiers. This is used while printing. */ struct d_print_mod { /* Next modifier on the list. These are in the reverse of the order in which they appeared in the mangled string. */ struct d_print_mod *next; /* The modifier. */ const struct demangle_component *mod; /* Whether this modifier was printed. */ int printed; /* The list of templates which applies to this modifier. */ struct d_print_template *templates; }; /* We use this structure to hold information during printing. */ struct d_print_info { /* The options passed to the demangler. */ int options; /* Buffer holding the result. */ char *buf; /* Current length of data in buffer. */ size_t len; /* Allocated size of buffer. */ size_t alc; /* The current list of templates, if any. */ struct d_print_template *templates; /* The current list of modifiers (e.g., pointer, reference, etc.), if any. */ struct d_print_mod *modifiers; /* Set to 1 if we had a memory allocation failure. */ int allocation_failure; }; #define d_print_saw_error(dpi) ((dpi)->buf == NULL) #define d_append_char(dpi, c) \ do \ { \ if ((dpi)->buf != NULL && (dpi)->len < (dpi)->alc) \ (dpi)->buf[(dpi)->len++] = (c); \ else \ d_print_append_char ((dpi), (c)); \ } \ while (0) #define d_append_buffer(dpi, s, l) \ do \ { \ if ((dpi)->buf != NULL && (dpi)->len + (l) <= (dpi)->alc) \ { \ memcpy ((dpi)->buf + (dpi)->len, (s), (l)); \ (dpi)->len += l; \ } \ else \ d_print_append_buffer ((dpi), (s), (l)); \ } \ while (0) #define d_append_string_constant(dpi, s) \ d_append_buffer (dpi, (s), sizeof (s) - 1) #define d_last_char(dpi) \ ((dpi)->buf == NULL || (dpi)->len == 0 ? '\0' : (dpi)->buf[(dpi)->len - 1]) #ifdef CP_DEMANGLE_DEBUG static void d_dump PARAMS ((struct demangle_component *, int)); #endif static struct demangle_component * d_make_empty PARAMS ((struct d_info *)); static struct demangle_component * d_make_comp PARAMS ((struct d_info *, enum demangle_component_type, struct demangle_component *, struct demangle_component *)); static struct demangle_component * d_make_name PARAMS ((struct d_info *, const char *, int)); static struct demangle_component * d_make_builtin_type PARAMS ((struct d_info *, const struct demangle_builtin_type_info *)); static struct demangle_component * d_make_operator PARAMS ((struct d_info *, const struct demangle_operator_info *)); static struct demangle_component * d_make_extended_operator PARAMS ((struct d_info *, int, struct demangle_component *)); static struct demangle_component * d_make_ctor PARAMS ((struct d_info *, enum gnu_v3_ctor_kinds, struct demangle_component *)); static struct demangle_component * d_make_dtor PARAMS ((struct d_info *, enum gnu_v3_dtor_kinds, struct demangle_component *)); static struct demangle_component * d_make_template_param PARAMS ((struct d_info *, long)); static struct demangle_component * d_make_sub PARAMS ((struct d_info *, const char *, int)); static int has_return_type PARAMS ((struct demangle_component *)); static int is_ctor_dtor_or_conversion PARAMS ((struct demangle_component *)); static struct demangle_component * d_encoding PARAMS ((struct d_info *, int)); static struct demangle_component * d_name PARAMS ((struct d_info *)); static struct demangle_component * d_nested_name PARAMS ((struct d_info *)); static struct demangle_component * d_prefix PARAMS ((struct d_info *)); static struct demangle_component * d_unqualified_name PARAMS ((struct d_info *)); static struct demangle_component * d_source_name PARAMS ((struct d_info *)); static long d_number PARAMS ((struct d_info *)); static struct demangle_component * d_identifier PARAMS ((struct d_info *, int)); static struct demangle_component * d_operator_name PARAMS ((struct d_info *)); static struct demangle_component * d_special_name PARAMS ((struct d_info *)); static int d_call_offset PARAMS ((struct d_info *, int)); static struct demangle_component * d_ctor_dtor_name PARAMS ((struct d_info *)); static struct demangle_component ** d_cv_qualifiers PARAMS ((struct d_info *, struct demangle_component **, int)); static struct demangle_component * d_function_type PARAMS ((struct d_info *)); static struct demangle_component * d_bare_function_type PARAMS ((struct d_info *, int)); static struct demangle_component * d_class_enum_type PARAMS ((struct d_info *)); static struct demangle_component * d_array_type PARAMS ((struct d_info *)); static struct demangle_component * d_pointer_to_member_type PARAMS ((struct d_info *)); static struct demangle_component * d_template_param PARAMS ((struct d_info *)); static struct demangle_component * d_template_args PARAMS ((struct d_info *)); static struct demangle_component * d_template_arg PARAMS ((struct d_info *)); static struct demangle_component * d_expression PARAMS ((struct d_info *)); static struct demangle_component * d_expr_primary PARAMS ((struct d_info *)); static struct demangle_component * d_local_name PARAMS ((struct d_info *)); static int d_discriminator PARAMS ((struct d_info *)); static int d_add_substitution PARAMS ((struct d_info *, struct demangle_component *)); static struct demangle_component * d_substitution PARAMS ((struct d_info *, int)); static void d_print_resize PARAMS ((struct d_print_info *, size_t)); static void d_print_append_char PARAMS ((struct d_print_info *, int)); static void d_print_append_buffer PARAMS ((struct d_print_info *, const char *, size_t)); static void d_print_error PARAMS ((struct d_print_info *)); static void d_print_comp PARAMS ((struct d_print_info *, const struct demangle_component *)); static void d_print_java_identifier PARAMS ((struct d_print_info *, const char *, int)); static void d_print_mod_list PARAMS ((struct d_print_info *, struct d_print_mod *, int)); static void d_print_mod PARAMS ((struct d_print_info *, const struct demangle_component *)); static void d_print_function_type PARAMS ((struct d_print_info *, const struct demangle_component *, struct d_print_mod *)); static void d_print_array_type PARAMS ((struct d_print_info *, const struct demangle_component *, struct d_print_mod *)); static void d_print_expr_op PARAMS ((struct d_print_info *, const struct demangle_component *)); static void d_print_cast PARAMS ((struct d_print_info *, const struct demangle_component *)); static char * d_demangle PARAMS ((const char *, int, size_t *)); #ifdef CP_DEMANGLE_DEBUG static void d_dump (dc, indent) struct demangle_component *dc; int indent; { int i; if (dc == NULL) return; for (i = 0; i < indent; ++i) putchar (' '); switch (dc->type) { case DEMANGLE_COMPONENT_NAME: printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s); return; case DEMANGLE_COMPONENT_TEMPLATE_PARAM: printf ("template parameter %ld\n", dc->u.s_number.number); return; case DEMANGLE_COMPONENT_CTOR: printf ("constructor %d\n", (int) dc->u.s_ctor.kind); d_dump (dc->u.s_ctor.name, indent + 2); return; case DEMANGLE_COMPONENT_DTOR: printf ("destructor %d\n", (int) dc->u.s_dtor.kind); d_dump (dc->u.s_dtor.name, indent + 2); return; case DEMANGLE_COMPONENT_SUB_STD: printf ("standard substitution %s\n", dc->u.s_string.string); return; case DEMANGLE_COMPONENT_BUILTIN_TYPE: printf ("builtin type %s\n", dc->u.s_builtin.type->name); return; case DEMANGLE_COMPONENT_OPERATOR: printf ("operator %s\n", dc->u.s_operator.op->name); return; case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: printf ("extended operator with %d args\n", dc->u.s_extended_operator.args); d_dump (dc->u.s_extended_operator.name, indent + 2); return; case DEMANGLE_COMPONENT_QUAL_NAME: printf ("qualified name\n"); break; case DEMANGLE_COMPONENT_LOCAL_NAME: printf ("local name\n"); break; case DEMANGLE_COMPONENT_TYPED_NAME: printf ("typed name\n"); break; case DEMANGLE_COMPONENT_TEMPLATE: printf ("template\n"); break; case DEMANGLE_COMPONENT_VTABLE: printf ("vtable\n"); break; case DEMANGLE_COMPONENT_VTT: printf ("VTT\n"); break; case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: printf ("construction vtable\n"); break; case DEMANGLE_COMPONENT_TYPEINFO: printf ("typeinfo\n"); break; case DEMANGLE_COMPONENT_TYPEINFO_NAME: printf ("typeinfo name\n"); break; case DEMANGLE_COMPONENT_TYPEINFO_FN: printf ("typeinfo function\n"); break; case DEMANGLE_COMPONENT_THUNK: printf ("thunk\n"); break; case DEMANGLE_COMPONENT_VIRTUAL_THUNK: printf ("virtual thunk\n"); break; case DEMANGLE_COMPONENT_COVARIANT_THUNK: printf ("covariant thunk\n"); break; case DEMANGLE_COMPONENT_JAVA_CLASS: printf ("java class\n"); break; case DEMANGLE_COMPONENT_GUARD: printf ("guard\n"); break; case DEMANGLE_COMPONENT_REFTEMP: printf ("reference temporary\n"); break; case DEMANGLE_COMPONENT_RESTRICT: printf ("restrict\n"); break; case DEMANGLE_COMPONENT_VOLATILE: printf ("volatile\n"); break; case DEMANGLE_COMPONENT_CONST: printf ("const\n"); break; case DEMANGLE_COMPONENT_RESTRICT_THIS: printf ("restrict this\n"); break; case DEMANGLE_COMPONENT_VOLATILE_THIS: printf ("volatile this\n"); break; case DEMANGLE_COMPONENT_CONST_THIS: printf ("const this\n"); break; case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: printf ("vendor type qualifier\n"); break; case DEMANGLE_COMPONENT_POINTER: printf ("pointer\n"); break; case DEMANGLE_COMPONENT_REFERENCE: printf ("reference\n"); break; case DEMANGLE_COMPONENT_COMPLEX: printf ("complex\n"); break; case DEMANGLE_COMPONENT_IMAGINARY: printf ("imaginary\n"); break; case DEMANGLE_COMPONENT_VENDOR_TYPE: printf ("vendor type\n"); break; case DEMANGLE_COMPONENT_FUNCTION_TYPE: printf ("function type\n"); break; case DEMANGLE_COMPONENT_ARRAY_TYPE: printf ("array type\n"); break; case DEMANGLE_COMPONENT_PTRMEM_TYPE: printf ("pointer to member type\n"); break; case DEMANGLE_COMPONENT_ARGLIST: printf ("argument list\n"); break; case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: printf ("template argument list\n"); break; case DEMANGLE_COMPONENT_CAST: printf ("cast\n"); break; case DEMANGLE_COMPONENT_UNARY: printf ("unary operator\n"); break; case DEMANGLE_COMPONENT_BINARY: printf ("binary operator\n"); break; case DEMANGLE_COMPONENT_BINARY_ARGS: printf ("binary operator arguments\n"); break; case DEMANGLE_COMPONENT_TRINARY: printf ("trinary operator\n"); break; case DEMANGLE_COMPONENT_TRINARY_ARG1: printf ("trinary operator arguments 1\n"); break; case DEMANGLE_COMPONENT_TRINARY_ARG2: printf ("trinary operator arguments 1\n"); break; case DEMANGLE_COMPONENT_LITERAL: printf ("literal\n"); break; case DEMANGLE_COMPONENT_LITERAL_NEG: printf ("negative literal\n"); break; } d_dump (d_left (dc), indent + 2); d_dump (d_right (dc), indent + 2); } #endif /* CP_DEMANGLE_DEBUG */ /* Fill in a DEMANGLE_COMPONENT_NAME. */ CP_STATIC_IF_GLIBCPP_V3 int cplus_demangle_fill_name (p, s, len) struct demangle_component *p; const char *s; int len; { if (p == NULL || s == NULL || len == 0) return 0; p->type = DEMANGLE_COMPONENT_NAME; p->u.s_name.s = s; p->u.s_name.len = len; return 1; } /* Fill in a DEMANGLE_COMPONENT_EXTENDED_OPERATOR. */ CP_STATIC_IF_GLIBCPP_V3 int cplus_demangle_fill_extended_operator (p, args, name) struct demangle_component *p; int args; struct demangle_component *name; { if (p == NULL || args < 0 || name == NULL) return 0; p->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR; p->u.s_extended_operator.args = args; p->u.s_extended_operator.name = name; return 1; } /* Fill in a DEMANGLE_COMPONENT_CTOR. */ CP_STATIC_IF_GLIBCPP_V3 int cplus_demangle_fill_ctor (p, kind, name) struct demangle_component *p; enum gnu_v3_ctor_kinds kind; struct demangle_component *name; { if (p == NULL || name == NULL || (kind < gnu_v3_complete_object_ctor && kind > gnu_v3_complete_object_allocating_ctor)) return 0; p->type = DEMANGLE_COMPONENT_CTOR; p->u.s_ctor.kind = kind; p->u.s_ctor.name = name; return 1; } /* Fill in a DEMANGLE_COMPONENT_DTOR. */ CP_STATIC_IF_GLIBCPP_V3 int cplus_demangle_fill_dtor (p, kind, name) struct demangle_component *p; enum gnu_v3_dtor_kinds kind; struct demangle_component *name; { if (p == NULL || name == NULL || (kind < gnu_v3_deleting_dtor && kind > gnu_v3_base_object_dtor)) return 0; p->type = DEMANGLE_COMPONENT_DTOR; p->u.s_dtor.kind = kind; p->u.s_dtor.name = name; return 1; } /* Add a new component. */ static struct demangle_component * d_make_empty (di) struct d_info *di; { struct demangle_component *p; if (di->next_comp >= di->num_comps) return NULL; p = &di->comps[di->next_comp]; ++di->next_comp; return p; } /* Add a new generic component. */ static struct demangle_component * d_make_comp (di, type, left, right) struct d_info *di; enum demangle_component_type type; struct demangle_component *left; struct demangle_component *right; { struct demangle_component *p; /* We check for errors here. A typical error would be a NULL return from a subroutine. We catch those here, and return NULL upward. */ switch (type) { /* These types require two parameters. */ case DEMANGLE_COMPONENT_QUAL_NAME: case DEMANGLE_COMPONENT_LOCAL_NAME: case DEMANGLE_COMPONENT_TYPED_NAME: case DEMANGLE_COMPONENT_TEMPLATE: case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: case DEMANGLE_COMPONENT_PTRMEM_TYPE: case DEMANGLE_COMPONENT_UNARY: case DEMANGLE_COMPONENT_BINARY: case DEMANGLE_COMPONENT_BINARY_ARGS: case DEMANGLE_COMPONENT_TRINARY: case DEMANGLE_COMPONENT_TRINARY_ARG1: case DEMANGLE_COMPONENT_TRINARY_ARG2: case DEMANGLE_COMPONENT_LITERAL: case DEMANGLE_COMPONENT_LITERAL_NEG: if (left == NULL || right == NULL) return NULL; break; /* These types only require one parameter. */ case DEMANGLE_COMPONENT_VTABLE: case DEMANGLE_COMPONENT_VTT: case DEMANGLE_COMPONENT_TYPEINFO: case DEMANGLE_COMPONENT_TYPEINFO_NAME: case DEMANGLE_COMPONENT_TYPEINFO_FN: case DEMANGLE_COMPONENT_THUNK: case DEMANGLE_COMPONENT_VIRTUAL_THUNK: case DEMANGLE_COMPONENT_COVARIANT_THUNK: case DEMANGLE_COMPONENT_JAVA_CLASS: case DEMANGLE_COMPONENT_GUARD: case DEMANGLE_COMPONENT_REFTEMP: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_REFERENCE: case DEMANGLE_COMPONENT_COMPLEX: case DEMANGLE_COMPONENT_IMAGINARY: case DEMANGLE_COMPONENT_VENDOR_TYPE: case DEMANGLE_COMPONENT_ARGLIST: case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: case DEMANGLE_COMPONENT_CAST: if (left == NULL) return NULL; break; /* This needs a right parameter, but the left parameter can be empty. */ case DEMANGLE_COMPONENT_ARRAY_TYPE: if (right == NULL) return NULL; break; /* These are allowed to have no parameters--in some cases they will be filled in later. */ case DEMANGLE_COMPONENT_FUNCTION_TYPE: case DEMANGLE_COMPONENT_RESTRICT: case DEMANGLE_COMPONENT_VOLATILE: case DEMANGLE_COMPONENT_CONST: case DEMANGLE_COMPONENT_RESTRICT_THIS: case DEMANGLE_COMPONENT_VOLATILE_THIS: case DEMANGLE_COMPONENT_CONST_THIS: break; /* Other types should not be seen here. */ default: return NULL; } p = d_make_empty (di); if (p != NULL) { p->type = type; p->u.s_binary.left = left; p->u.s_binary.right = right; } return p; } /* Add a new name component. */ static struct demangle_component * d_make_name (di, s, len) struct d_info *di; const char *s; int len; { struct demangle_component *p; p = d_make_empty (di); if (! cplus_demangle_fill_name (p, s, len)) return NULL; return p; } /* Add a new builtin type component. */ static struct demangle_component * d_make_builtin_type (di, type) struct d_info *di; const struct demangle_builtin_type_info *type; { struct demangle_component *p; if (type == NULL) return NULL; p = d_make_empty (di); if (p != NULL) { p->type = DEMANGLE_COMPONENT_BUILTIN_TYPE; p->u.s_builtin.type = type; } return p; } /* Add a new operator component. */ static struct demangle_component * d_make_operator (di, op) struct d_info *di; const struct demangle_operator_info *op; { struct demangle_component *p; p = d_make_empty (di); if (p != NULL) { p->type = DEMANGLE_COMPONENT_OPERATOR; p->u.s_operator.op = op; } return p; } /* Add a new extended operator component. */ static struct demangle_component * d_make_extended_operator (di, args, name) struct d_info *di; int args; struct demangle_component *name; { struct demangle_component *p; p = d_make_empty (di); if (! cplus_demangle_fill_extended_operator (p, args, name)) return NULL; return p; } /* Add a new constructor component. */ static struct demangle_component * d_make_ctor (di, kind, name) struct d_info *di; enum gnu_v3_ctor_kinds kind; struct demangle_component *name; { struct demangle_component *p; p = d_make_empty (di); if (! cplus_demangle_fill_ctor (p, kind, name)) return NULL; return p; } /* Add a new destructor component. */ static struct demangle_component * d_make_dtor (di, kind, name) struct d_info *di; enum gnu_v3_dtor_kinds kind; struct demangle_component *name; { struct demangle_component *p; p = d_make_empty (di); if (! cplus_demangle_fill_dtor (p, kind, name)) return NULL; return p; } /* Add a new template parameter. */ static struct demangle_component * d_make_template_param (di, i) struct d_info *di; long i; { struct demangle_component *p; p = d_make_empty (di); if (p != NULL) { p->type = DEMANGLE_COMPONENT_TEMPLATE_PARAM; p->u.s_number.number = i; } return p; } /* Add a new standard substitution component. */ static struct demangle_component * d_make_sub (di, name, len) struct d_info *di; const char *name; int len; { struct demangle_component *p; p = d_make_empty (di); if (p != NULL) { p->type = DEMANGLE_COMPONENT_SUB_STD; p->u.s_string.string = name; p->u.s_string.len = len; } return p; } /* ::= _Z TOP_LEVEL is non-zero when called at the top level. */ CP_STATIC_IF_GLIBCPP_V3 struct demangle_component * cplus_demangle_mangled_name (di, top_level) struct d_info *di; int top_level; { if (d_next_char (di) != '_') return NULL; if (d_next_char (di) != 'Z') return NULL; return d_encoding (di, top_level); } /* Return whether a function should have a return type. The argument is the function name, which may be qualified in various ways. The rules are that template functions have return types with some exceptions, function types which are not part of a function name mangling have return types with some exceptions, and non-template function names do not have return types. The exceptions are that constructors, destructors, and conversion operators do not have return types. */ static int has_return_type (dc) struct demangle_component *dc; { if (dc == NULL) return 0; switch (dc->type) { default: return 0; case DEMANGLE_COMPONENT_TEMPLATE: return ! is_ctor_dtor_or_conversion (d_left (dc)); case DEMANGLE_COMPONENT_RESTRICT_THIS: case DEMANGLE_COMPONENT_VOLATILE_THIS: case DEMANGLE_COMPONENT_CONST_THIS: return has_return_type (d_left (dc)); } } /* Return whether a name is a constructor, a destructor, or a conversion operator. */ static int is_ctor_dtor_or_conversion (dc) struct demangle_component *dc; { if (dc == NULL) return 0; switch (dc->type) { default: return 0; case DEMANGLE_COMPONENT_QUAL_NAME: case DEMANGLE_COMPONENT_LOCAL_NAME: return is_ctor_dtor_or_conversion (d_right (dc)); case DEMANGLE_COMPONENT_CTOR: case DEMANGLE_COMPONENT_DTOR: case DEMANGLE_COMPONENT_CAST: return 1; } } /* ::= <(function) name> ::= <(data) name> ::= TOP_LEVEL is non-zero when called at the top level, in which case if DMGL_PARAMS is not set we do not demangle the function parameters. We only set this at the top level, because otherwise we would not correctly demangle names in local scopes. */ static struct demangle_component * d_encoding (di, top_level) struct d_info *di; int top_level; { char peek = d_peek_char (di); if (peek == 'G' || peek == 'T') return d_special_name (di); else { struct demangle_component *dc; dc = d_name (di); if (dc != NULL && top_level && (di->options & DMGL_PARAMS) == 0) { /* Strip off any initial CV-qualifiers, as they really apply to the `this' parameter, and they were not output by the v2 demangler without DMGL_PARAMS. */ while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS || dc->type == DEMANGLE_COMPONENT_CONST_THIS) dc = d_left (dc); /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then there may be CV-qualifiers on its right argument which really apply here; this happens when parsing a class which is local to a function. */ if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME) { struct demangle_component *dcr; dcr = d_right (dc); while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS || dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS || dcr->type == DEMANGLE_COMPONENT_CONST_THIS) dcr = d_left (dcr); dc->u.s_binary.right = dcr; } return dc; } peek = d_peek_char (di); if (peek == '\0' || peek == 'E') return dc; return d_make_comp (di, DEMANGLE_COMPONENT_TYPED_NAME, dc, d_bare_function_type (di, has_return_type (dc))); } } /* ::= ::= ::= ::= ::= ::= St ::= ::= */ static struct demangle_component * d_name (di) struct d_info *di; { char peek = d_peek_char (di); struct demangle_component *dc; switch (peek) { case 'N': return d_nested_name (di); case 'Z': return d_local_name (di); case 'S': { int subst; if (d_peek_next_char (di) != 't') { dc = d_substitution (di, 0); subst = 1; } else { d_advance (di, 2); dc = d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, d_make_name (di, "std", 3), d_unqualified_name (di)); di->expansion += 3; subst = 0; } if (d_peek_char (di) != 'I') { /* The grammar does not permit this case to occur if we called d_substitution() above (i.e., subst == 1). We don't bother to check. */ } else { /* This is , which means that we just saw , which is a substitution candidate if we didn't just get it from a substitution. */ if (! subst) { if (! d_add_substitution (di, dc)) return NULL; } dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc, d_template_args (di)); } return dc; } default: dc = d_unqualified_name (di); if (d_peek_char (di) == 'I') { /* This is , which means that we just saw , which is a substitution candidate. */ if (! d_add_substitution (di, dc)) return NULL; dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc, d_template_args (di)); } return dc; } } /* ::= N [] E ::= N [] E */ static struct demangle_component * d_nested_name (di) struct d_info *di; { struct demangle_component *ret; struct demangle_component **pret; if (d_next_char (di) != 'N') return NULL; pret = d_cv_qualifiers (di, &ret, 1); if (pret == NULL) return NULL; *pret = d_prefix (di); if (*pret == NULL) return NULL; if (d_next_char (di) != 'E') return NULL; return ret; } /* ::= ::= ::= ::= ::= ::= <(template) unqualified-name> ::= ::= */ static struct demangle_component * d_prefix (di) struct d_info *di; { struct demangle_component *ret = NULL; while (1) { char peek; enum demangle_component_type comb_type; struct demangle_component *dc; peek = d_peek_char (di); if (peek == '\0') return NULL; /* The older code accepts a here, but I don't see that in the grammar. The older code does not accept a here. */ comb_type = DEMANGLE_COMPONENT_QUAL_NAME; if (IS_DIGIT (peek) || IS_LOWER (peek) || peek == 'C' || peek == 'D' || peek == 'L') dc = d_unqualified_name (di); else if (peek == 'S') dc = d_substitution (di, 1); else if (peek == 'I') { if (ret == NULL) return NULL; comb_type = DEMANGLE_COMPONENT_TEMPLATE; dc = d_template_args (di); } else if (peek == 'T') dc = d_template_param (di); else if (peek == 'E') return ret; else return NULL; if (ret == NULL) ret = dc; else ret = d_make_comp (di, comb_type, ret, dc); if (peek != 'S' && d_peek_char (di) != 'E') { if (! d_add_substitution (di, ret)) return NULL; } } } /* ::= ::= ::= ::= ::= L */ static struct demangle_component * d_unqualified_name (di) struct d_info *di; { char peek; peek = d_peek_char (di); if (IS_DIGIT (peek)) return d_source_name (di); else if (IS_LOWER (peek)) { struct demangle_component *ret; ret = d_operator_name (di); if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR) di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2; return ret; } else if (peek == 'C' || peek == 'D') return d_ctor_dtor_name (di); else if (peek == 'L') { struct demangle_component * ret; d_advance (di, 1); ret = d_source_name (di); if (ret == NULL) return NULL; if (! d_discriminator (di)) return NULL; return ret; } else return NULL; } /* ::= <(positive length) number> */ static struct demangle_component * d_source_name (di) struct d_info *di; { long len; struct demangle_component *ret; len = d_number (di); if (len <= 0) return NULL; ret = d_identifier (di, len); di->last_name = ret; return ret; } /* number ::= [n] <(non-negative decimal integer)> */ static long d_number (di) struct d_info *di; { int negative; char peek; long ret; negative = 0; peek = d_peek_char (di); if (peek == 'n') { negative = 1; d_advance (di, 1); peek = d_peek_char (di); } ret = 0; while (1) { if (! IS_DIGIT (peek)) { if (negative) ret = - ret; return ret; } ret = ret * 10 + peek - '0'; d_advance (di, 1); peek = d_peek_char (di); } } /* identifier ::= <(unqualified source code identifier)> */ static struct demangle_component * d_identifier (di, len) struct d_info *di; int len; { const char *name; name = d_str (di); if (di->send - name < len) return NULL; d_advance (di, len); /* A Java mangled name may have a trailing '$' if it is a C++ keyword. This '$' is not included in the length count. We just ignore the '$'. */ if ((di->options & DMGL_JAVA) != 0 && d_peek_char (di) == '$') d_advance (di, 1); /* Look for something which looks like a gcc encoding of an anonymous namespace, and replace it with a more user friendly name. */ if (len >= (int) ANONYMOUS_NAMESPACE_PREFIX_LEN + 2 && memcmp (name, ANONYMOUS_NAMESPACE_PREFIX, ANONYMOUS_NAMESPACE_PREFIX_LEN) == 0) { const char *s; s = name + ANONYMOUS_NAMESPACE_PREFIX_LEN; if ((*s == '.' || *s == '_' || *s == '$') && s[1] == 'N') { di->expansion -= len - sizeof "(anonymous namespace)"; return d_make_name (di, "(anonymous namespace)", sizeof "(anonymous namespace)" - 1); } } return d_make_name (di, name, len); } /* operator_name ::= many different two character encodings. ::= cv ::= v */ #define NL(s) s, (sizeof s) - 1 CP_STATIC_IF_GLIBCPP_V3 const struct demangle_operator_info cplus_demangle_operators[] = { { "aN", NL ("&="), 2 }, { "aS", NL ("="), 2 }, { "aa", NL ("&&"), 2 }, { "ad", NL ("&"), 1 }, { "an", NL ("&"), 2 }, { "cl", NL ("()"), 0 }, { "cm", NL (","), 2 }, { "co", NL ("~"), 1 }, { "dV", NL ("/="), 2 }, { "da", NL ("delete[]"), 1 }, { "de", NL ("*"), 1 }, { "dl", NL ("delete"), 1 }, { "dv", NL ("/"), 2 }, { "eO", NL ("^="), 2 }, { "eo", NL ("^"), 2 }, { "eq", NL ("=="), 2 }, { "ge", NL (">="), 2 }, { "gt", NL (">"), 2 }, { "ix", NL ("[]"), 2 }, { "lS", NL ("<<="), 2 }, { "le", NL ("<="), 2 }, { "ls", NL ("<<"), 2 }, { "lt", NL ("<"), 2 }, { "mI", NL ("-="), 2 }, { "mL", NL ("*="), 2 }, { "mi", NL ("-"), 2 }, { "ml", NL ("*"), 2 }, { "mm", NL ("--"), 1 }, { "na", NL ("new[]"), 1 }, { "ne", NL ("!="), 2 }, { "ng", NL ("-"), 1 }, { "nt", NL ("!"), 1 }, { "nw", NL ("new"), 1 }, { "oR", NL ("|="), 2 }, { "oo", NL ("||"), 2 }, { "or", NL ("|"), 2 }, { "pL", NL ("+="), 2 }, { "pl", NL ("+"), 2 }, { "pm", NL ("->*"), 2 }, { "pp", NL ("++"), 1 }, { "ps", NL ("+"), 1 }, { "pt", NL ("->"), 2 }, { "qu", NL ("?"), 3 }, { "rM", NL ("%="), 2 }, { "rS", NL (">>="), 2 }, { "rm", NL ("%"), 2 }, { "rs", NL (">>"), 2 }, { "st", NL ("sizeof "), 1 }, { "sz", NL ("sizeof "), 1 }, { NULL, NULL, 0, 0 } }; static struct demangle_component * d_operator_name (di) struct d_info *di; { char c1; char c2; c1 = d_next_char (di); c2 = d_next_char (di); if (c1 == 'v' && IS_DIGIT (c2)) return d_make_extended_operator (di, c2 - '0', d_source_name (di)); else if (c1 == 'c' && c2 == 'v') return d_make_comp (di, DEMANGLE_COMPONENT_CAST, cplus_demangle_type (di), NULL); else { /* LOW is the inclusive lower bound. */ int low = 0; /* HIGH is the exclusive upper bound. We subtract one to ignore the sentinel at the end of the array. */ int high = ((sizeof (cplus_demangle_operators) / sizeof (cplus_demangle_operators[0])) - 1); while (1) { int i; const struct demangle_operator_info *p; i = low + (high - low) / 2; p = cplus_demangle_operators + i; if (c1 == p->code[0] && c2 == p->code[1]) return d_make_operator (di, p); if (c1 < p->code[0] || (c1 == p->code[0] && c2 < p->code[1])) high = i; else low = i + 1; if (low == high) return NULL; } } } /* ::= TV ::= TT ::= TI ::= TS ::= GV <(object) name> ::= T <(base) encoding> ::= Tc <(base) encoding> Also g++ extensions: ::= TC <(offset) number> _ <(base) type> ::= TF ::= TJ ::= GR */ static struct demangle_component * d_special_name (di) struct d_info *di; { char c; di->expansion += 20; c = d_next_char (di); if (c == 'T') { switch (d_next_char (di)) { case 'V': di->expansion -= 5; return d_make_comp (di, DEMANGLE_COMPONENT_VTABLE, cplus_demangle_type (di), NULL); case 'T': di->expansion -= 10; return d_make_comp (di, DEMANGLE_COMPONENT_VTT, cplus_demangle_type (di), NULL); case 'I': return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO, cplus_demangle_type (di), NULL); case 'S': return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_NAME, cplus_demangle_type (di), NULL); case 'h': if (! d_call_offset (di, 'h')) return NULL; return d_make_comp (di, DEMANGLE_COMPONENT_THUNK, d_encoding (di, 0), NULL); case 'v': if (! d_call_offset (di, 'v')) return NULL; return d_make_comp (di, DEMANGLE_COMPONENT_VIRTUAL_THUNK, d_encoding (di, 0), NULL); case 'c': if (! d_call_offset (di, '\0')) return NULL; if (! d_call_offset (di, '\0')) return NULL; return d_make_comp (di, DEMANGLE_COMPONENT_COVARIANT_THUNK, d_encoding (di, 0), NULL); case 'C': { struct demangle_component *derived_type; long offset; struct demangle_component *base_type; derived_type = cplus_demangle_type (di); offset = d_number (di); if (offset < 0) return NULL; if (d_next_char (di) != '_') return NULL; base_type = cplus_demangle_type (di); /* We don't display the offset. FIXME: We should display it in verbose mode. */ di->expansion += 5; return d_make_comp (di, DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, base_type, derived_type); } case 'F': return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_FN, cplus_demangle_type (di), NULL); case 'J': return d_make_comp (di, DEMANGLE_COMPONENT_JAVA_CLASS, cplus_demangle_type (di), NULL); default: return NULL; } } else if (c == 'G') { switch (d_next_char (di)) { case 'V': return d_make_comp (di, DEMANGLE_COMPONENT_GUARD, d_name (di), NULL); case 'R': return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, d_name (di), NULL); default: return NULL; } } else return NULL; } /* ::= h _ ::= v _ ::= <(offset) number> ::= <(offset) number> _ <(virtual offset) number> The C parameter, if not '\0', is a character we just read which is the start of the . We don't display the offset information anywhere. FIXME: We should display it in verbose mode. */ static int d_call_offset (di, c) struct d_info *di; int c; { if (c == '\0') c = d_next_char (di); if (c == 'h') d_number (di); else if (c == 'v') { d_number (di); if (d_next_char (di) != '_') return 0; d_number (di); } else return 0; if (d_next_char (di) != '_') return 0; return 1; } /* ::= C1 ::= C2 ::= C3 ::= D0 ::= D1 ::= D2 */ static struct demangle_component * d_ctor_dtor_name (di) struct d_info *di; { if (di->last_name != NULL) { if (di->last_name->type == DEMANGLE_COMPONENT_NAME) di->expansion += di->last_name->u.s_name.len; else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD) di->expansion += di->last_name->u.s_string.len; } switch (d_next_char (di)) { case 'C': { enum gnu_v3_ctor_kinds kind; switch (d_next_char (di)) { case '1': kind = gnu_v3_complete_object_ctor; break; case '2': kind = gnu_v3_base_object_ctor; break; case '3': kind = gnu_v3_complete_object_allocating_ctor; break; default: return NULL; } return d_make_ctor (di, kind, di->last_name); } case 'D': { enum gnu_v3_dtor_kinds kind; switch (d_next_char (di)) { case '0': kind = gnu_v3_deleting_dtor; break; case '1': kind = gnu_v3_complete_object_dtor; break; case '2': kind = gnu_v3_base_object_dtor; break; default: return NULL; } return d_make_dtor (di, kind, di->last_name); } default: return NULL; } } /* ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= P ::= R ::= C ::= G ::= U ::= various one letter codes ::= u */ CP_STATIC_IF_GLIBCPP_V3 const struct demangle_builtin_type_info cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] = { /* a */ { NL ("signed char"), NL ("signed char"), D_PRINT_DEFAULT }, /* b */ { NL ("bool"), NL ("boolean"), D_PRINT_BOOL }, /* c */ { NL ("char"), NL ("byte"), D_PRINT_DEFAULT }, /* d */ { NL ("double"), NL ("double"), D_PRINT_FLOAT }, /* e */ { NL ("long double"), NL ("long double"), D_PRINT_FLOAT }, /* f */ { NL ("float"), NL ("float"), D_PRINT_FLOAT }, /* g */ { NL ("__float128"), NL ("__float128"), D_PRINT_FLOAT }, /* h */ { NL ("unsigned char"), NL ("unsigned char"), D_PRINT_DEFAULT }, /* i */ { NL ("int"), NL ("int"), D_PRINT_INT }, /* j */ { NL ("unsigned int"), NL ("unsigned"), D_PRINT_UNSIGNED }, /* k */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, /* l */ { NL ("long"), NL ("long"), D_PRINT_LONG }, /* m */ { NL ("unsigned long"), NL ("unsigned long"), D_PRINT_UNSIGNED_LONG }, /* n */ { NL ("__int128"), NL ("__int128"), D_PRINT_DEFAULT }, /* o */ { NL ("unsigned __int128"), NL ("unsigned __int128"), D_PRINT_DEFAULT }, /* p */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, /* q */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, /* r */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, /* s */ { NL ("short"), NL ("short"), D_PRINT_DEFAULT }, /* t */ { NL ("unsigned short"), NL ("unsigned short"), D_PRINT_DEFAULT }, /* u */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT }, /* v */ { NL ("void"), NL ("void"), D_PRINT_VOID }, /* w */ { NL ("wchar_t"), NL ("char"), D_PRINT_DEFAULT }, /* x */ { NL ("long long"), NL ("long"), D_PRINT_LONG_LONG }, /* y */ { NL ("unsigned long long"), NL ("unsigned long long"), D_PRINT_UNSIGNED_LONG_LONG }, /* z */ { NL ("..."), NL ("..."), D_PRINT_DEFAULT }, }; CP_STATIC_IF_GLIBCPP_V3 struct demangle_component * cplus_demangle_type (di) struct d_info *di; { char peek; struct demangle_component *ret; int can_subst; /* The ABI specifies that when CV-qualifiers are used, the base type is substitutable, and the fully qualified type is substitutable, but the base type with a strict subset of the CV-qualifiers is not substitutable. The natural recursive implementation of the CV-qualifiers would cause subsets to be substitutable, so instead we pull them all off now. FIXME: The ABI says that order-insensitive vendor qualifiers should be handled in the same way, but we have no way to tell which vendor qualifiers are order-insensitive and which are order-sensitive. So we just assume that they are all order-sensitive. g++ 3.4 supports only one vendor qualifier, __vector, and it treats it as order-sensitive when mangling names. */ peek = d_peek_char (di); if (peek == 'r' || peek == 'V' || peek == 'K') { struct demangle_component **pret; pret = d_cv_qualifiers (di, &ret, 0); if (pret == NULL) return NULL; *pret = cplus_demangle_type (di); if (! d_add_substitution (di, ret)) return NULL; return ret; } can_subst = 1; switch (peek) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'l': case 'm': case 'n': case 'o': case 's': case 't': case 'v': case 'w': case 'x': case 'y': case 'z': ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[peek - 'a']); di->expansion += ret->u.s_builtin.type->len; can_subst = 0; d_advance (di, 1); break; case 'u': d_advance (di, 1); ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE, d_source_name (di), NULL); break; case 'F': ret = d_function_type (di); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'N': case 'Z': ret = d_class_enum_type (di); break; case 'A': ret = d_array_type (di); break; case 'M': ret = d_pointer_to_member_type (di); break; case 'T': ret = d_template_param (di); if (d_peek_char (di) == 'I') { /* This is . The part is a substitution candidate. */ if (! d_add_substitution (di, ret)) return NULL; ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, d_template_args (di)); } break; case 'S': /* If this is a special substitution, then it is the start of . */ { char peek_next; peek_next = d_peek_next_char (di); if (IS_DIGIT (peek_next) || peek_next == '_' || IS_UPPER (peek_next)) { ret = d_substitution (di, 0); /* The substituted name may have been a template name and may be followed by tepmlate args. */ if (d_peek_char (di) == 'I') ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, d_template_args (di)); else can_subst = 0; } else { ret = d_class_enum_type (di); /* If the substitution was a complete type, then it is not a new substitution candidate. However, if the substitution was followed by template arguments, then the whole thing is a substitution candidate. */ if (ret != NULL && ret->type == DEMANGLE_COMPONENT_SUB_STD) can_subst = 0; } } break; case 'P': d_advance (di, 1); ret = d_make_comp (di, DEMANGLE_COMPONENT_POINTER, cplus_demangle_type (di), NULL); break; case 'R': d_advance (di, 1); ret = d_make_comp (di, DEMANGLE_COMPONENT_REFERENCE, cplus_demangle_type (di), NULL); break; case 'C': d_advance (di, 1); ret = d_make_comp (di, DEMANGLE_COMPONENT_COMPLEX, cplus_demangle_type (di), NULL); break; case 'G': d_advance (di, 1); ret = d_make_comp (di, DEMANGLE_COMPONENT_IMAGINARY, cplus_demangle_type (di), NULL); break; case 'U': d_advance (di, 1); ret = d_source_name (di); ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL, cplus_demangle_type (di), ret); break; default: return NULL; } if (can_subst) { if (! d_add_substitution (di, ret)) return NULL; } return ret; } /* ::= [r] [V] [K] */ static struct demangle_component ** d_cv_qualifiers (di, pret, member_fn) struct d_info *di; struct demangle_component **pret; int member_fn; { char peek; peek = d_peek_char (di); while (peek == 'r' || peek == 'V' || peek == 'K') { enum demangle_component_type t; d_advance (di, 1); if (peek == 'r') { t = (member_fn ? DEMANGLE_COMPONENT_RESTRICT_THIS : DEMANGLE_COMPONENT_RESTRICT); di->expansion += sizeof "restrict"; } else if (peek == 'V') { t = (member_fn ? DEMANGLE_COMPONENT_VOLATILE_THIS : DEMANGLE_COMPONENT_VOLATILE); di->expansion += sizeof "volatile"; } else { t = (member_fn ? DEMANGLE_COMPONENT_CONST_THIS : DEMANGLE_COMPONENT_CONST); di->expansion += sizeof "const"; } *pret = d_make_comp (di, t, NULL, NULL); if (*pret == NULL) return NULL; pret = &d_left (*pret); peek = d_peek_char (di); } return pret; } /* ::= F [Y] E */ static struct demangle_component * d_function_type (di) struct d_info *di; { struct demangle_component *ret; if (d_next_char (di) != 'F') return NULL; if (d_peek_char (di) == 'Y') { /* Function has C linkage. We don't print this information. FIXME: We should print it in verbose mode. */ d_advance (di, 1); } ret = d_bare_function_type (di, 1); if (d_next_char (di) != 'E') return NULL; return ret; } /* ::= + */ static struct demangle_component * d_bare_function_type (di, has_return_type) struct d_info *di; int has_return_type; { struct demangle_component *return_type; struct demangle_component *tl; struct demangle_component **ptl; return_type = NULL; tl = NULL; ptl = &tl; while (1) { char peek; struct demangle_component *type; peek = d_peek_char (di); if (peek == '\0' || peek == 'E') break; type = cplus_demangle_type (di); if (type == NULL) return NULL; if (has_return_type) { return_type = type; has_return_type = 0; } else { *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL); if (*ptl == NULL) return NULL; ptl = &d_right (*ptl); } } /* There should be at least one parameter type besides the optional return type. A function which takes no arguments will have a single parameter type void. */ if (tl == NULL) return NULL; /* If we have a single parameter type void, omit it. */ if (d_right (tl) == NULL && d_left (tl)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE && d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID) { di->expansion -= d_left (tl)->u.s_builtin.type->len; tl = NULL; } return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE, return_type, tl); } /* ::= */ static struct demangle_component * d_class_enum_type (di) struct d_info *di; { return d_name (di); } /* ::= A <(positive dimension) number> _ <(element) type> ::= A [<(dimension) expression>] _ <(element) type> */ static struct demangle_component * d_array_type (di) struct d_info *di; { char peek; struct demangle_component *dim; if (d_next_char (di) != 'A') return NULL; peek = d_peek_char (di); if (peek == '_') dim = NULL; else if (IS_DIGIT (peek)) { const char *s; s = d_str (di); do { d_advance (di, 1); peek = d_peek_char (di); } while (IS_DIGIT (peek)); dim = d_make_name (di, s, d_str (di) - s); if (dim == NULL) return NULL; } else { dim = d_expression (di); if (dim == NULL) return NULL; } if (d_next_char (di) != '_') return NULL; return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim, cplus_demangle_type (di)); } /* ::= M <(class) type> <(member) type> */ static struct demangle_component * d_pointer_to_member_type (di) struct d_info *di; { struct demangle_component *cl; struct demangle_component *mem; struct demangle_component **pmem; if (d_next_char (di) != 'M') return NULL; cl = cplus_demangle_type (di); /* The ABI specifies that any type can be a substitution source, and that M is followed by two types, and that when a CV-qualified type is seen both the base type and the CV-qualified types are substitution sources. The ABI also specifies that for a pointer to a CV-qualified member function, the qualifiers are attached to the second type. Given the grammar, a plain reading of the ABI suggests that both the CV-qualified member function and the non-qualified member function are substitution sources. However, g++ does not work that way. g++ treats only the CV-qualified member function as a substitution source. FIXME. So to work with g++, we need to pull off the CV-qualifiers here, in order to avoid calling add_substitution() in cplus_demangle_type(). */ pmem = d_cv_qualifiers (di, &mem, 1); if (pmem == NULL) return NULL; *pmem = cplus_demangle_type (di); return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem); } /* ::= T_ ::= T <(parameter-2 non-negative) number> _ */ static struct demangle_component * d_template_param (di) struct d_info *di; { long param; if (d_next_char (di) != 'T') return NULL; if (d_peek_char (di) == '_') param = 0; else { param = d_number (di); if (param < 0) return NULL; param += 1; } if (d_next_char (di) != '_') return NULL; ++di->did_subs; return d_make_template_param (di, param); } /* ::= I + E */ static struct demangle_component * d_template_args (di) struct d_info *di; { struct demangle_component *hold_last_name; struct demangle_component *al; struct demangle_component **pal; /* Preserve the last name we saw--don't let the template arguments clobber it, as that would give us the wrong name for a subsequent constructor or destructor. */ hold_last_name = di->last_name; if (d_next_char (di) != 'I') return NULL; al = NULL; pal = &al; while (1) { struct demangle_component *a; a = d_template_arg (di); if (a == NULL) return NULL; *pal = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, a, NULL); if (*pal == NULL) return NULL; pal = &d_right (*pal); if (d_peek_char (di) == 'E') { d_advance (di, 1); break; } } di->last_name = hold_last_name; return al; } /* ::= ::= X E ::= */ static struct demangle_component * d_template_arg (di) struct d_info *di; { struct demangle_component *ret; switch (d_peek_char (di)) { case 'X': d_advance (di, 1); ret = d_expression (di); if (d_next_char (di) != 'E') return NULL; return ret; case 'L': return d_expr_primary (di); default: return cplus_demangle_type (di); } } /* ::= <(unary) operator-name> ::= <(binary) operator-name> ::= <(trinary) operator-name> ::= st ::= ::= sr ::= sr ::= */ static struct demangle_component * d_expression (di) struct d_info *di; { char peek; peek = d_peek_char (di); if (peek == 'L') return d_expr_primary (di); else if (peek == 'T') return d_template_param (di); else if (peek == 's' && d_peek_next_char (di) == 'r') { struct demangle_component *type; struct demangle_component *name; d_advance (di, 2); type = cplus_demangle_type (di); name = d_unqualified_name (di); if (d_peek_char (di) != 'I') return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name); else return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, d_template_args (di))); } else { struct demangle_component *op; int args; op = d_operator_name (di); if (op == NULL) return NULL; if (op->type == DEMANGLE_COMPONENT_OPERATOR) di->expansion += op->u.s_operator.op->len - 2; if (op->type == DEMANGLE_COMPONENT_OPERATOR && strcmp (op->u.s_operator.op->code, "st") == 0) return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, cplus_demangle_type (di)); switch (op->type) { default: return NULL; case DEMANGLE_COMPONENT_OPERATOR: args = op->u.s_operator.op->args; break; case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: args = op->u.s_extended_operator.args; break; case DEMANGLE_COMPONENT_CAST: args = 1; break; } switch (args) { case 1: return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, d_expression (di)); case 2: { struct demangle_component *left; left = d_expression (di); return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op, d_make_comp (di, DEMANGLE_COMPONENT_BINARY_ARGS, left, d_expression (di))); } case 3: { struct demangle_component *first; struct demangle_component *second; first = d_expression (di); second = d_expression (di); return d_make_comp (di, DEMANGLE_COMPONENT_TRINARY, op, d_make_comp (di, DEMANGLE_COMPONENT_TRINARY_ARG1, first, d_make_comp (di, DEMANGLE_COMPONENT_TRINARY_ARG2, second, d_expression (di)))); } default: return NULL; } } } /* ::= L <(value) number> E ::= L <(value) float> E ::= L E */ static struct demangle_component * d_expr_primary (di) struct d_info *di; { struct demangle_component *ret; if (d_next_char (di) != 'L') return NULL; if (d_peek_char (di) == '_') ret = cplus_demangle_mangled_name (di, 0); else { struct demangle_component *type; enum demangle_component_type t; const char *s; type = cplus_demangle_type (di); if (type == NULL) return NULL; /* If we have a type we know how to print, we aren't going to print the type name itself. */ if (type->type == DEMANGLE_COMPONENT_BUILTIN_TYPE && type->u.s_builtin.type->print != D_PRINT_DEFAULT) di->expansion -= type->u.s_builtin.type->len; /* Rather than try to interpret the literal value, we just collect it as a string. Note that it's possible to have a floating point literal here. The ABI specifies that the format of such literals is machine independent. That's fine, but what's not fine is that versions of g++ up to 3.2 with -fabi-version=1 used upper case letters in the hex constant, and dumped out gcc's internal representation. That makes it hard to tell where the constant ends, and hard to dump the constant in any readable form anyhow. We don't attempt to handle these cases. */ t = DEMANGLE_COMPONENT_LITERAL; if (d_peek_char (di) == 'n') { t = DEMANGLE_COMPONENT_LITERAL_NEG; d_advance (di, 1); } s = d_str (di); while (d_peek_char (di) != 'E') d_advance (di, 1); ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s)); } if (d_next_char (di) != 'E') return NULL; return ret; } /* ::= Z <(function) encoding> E <(entity) name> [] ::= Z <(function) encoding> E s [] */ static struct demangle_component * d_local_name (di) struct d_info *di; { struct demangle_component *function; if (d_next_char (di) != 'Z') return NULL; function = d_encoding (di, 0); if (d_next_char (di) != 'E') return NULL; if (d_peek_char (di) == 's') { d_advance (di, 1); if (! d_discriminator (di)) return NULL; return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, d_make_name (di, "string literal", sizeof "string literal" - 1)); } else { struct demangle_component *name; name = d_name (di); if (! d_discriminator (di)) return NULL; return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, name); } } /* ::= _ <(non-negative) number> We demangle the discriminator, but we don't print it out. FIXME: We should print it out in verbose mode. */ static int d_discriminator (di) struct d_info *di; { long discrim; if (d_peek_char (di) != '_') return 1; d_advance (di, 1); discrim = d_number (di); if (discrim < 0) return 0; return 1; } /* Add a new substitution. */ static int d_add_substitution (di, dc) struct d_info *di; struct demangle_component *dc; { if (dc == NULL) return 0; if (di->next_sub >= di->num_subs) return 0; di->subs[di->next_sub] = dc; ++di->next_sub; return 1; } /* ::= S _ ::= S_ ::= St ::= Sa ::= Sb ::= Ss ::= Si ::= So ::= Sd If PREFIX is non-zero, then this type is being used as a prefix in a qualified name. In this case, for the standard substitutions, we need to check whether we are being used as a prefix for a constructor or destructor, and return a full template name. Otherwise we will get something like std::iostream::~iostream() which does not correspond particularly well to any function which actually appears in the source. */ static const struct d_standard_sub_info standard_subs[] = { { 't', NL ("std"), NL ("std"), NULL, 0 }, { 'a', NL ("std::allocator"), NL ("std::allocator"), NL ("allocator") }, { 'b', NL ("std::basic_string"), NL ("std::basic_string"), NL ("basic_string") }, { 's', NL ("std::string"), NL ("std::basic_string, std::allocator >"), NL ("basic_string") }, { 'i', NL ("std::istream"), NL ("std::basic_istream >"), NL ("basic_istream") }, { 'o', NL ("std::ostream"), NL ("std::basic_ostream >"), NL ("basic_ostream") }, { 'd', NL ("std::iostream"), NL ("std::basic_iostream >"), NL ("basic_iostream") } }; static struct demangle_component * d_substitution (di, prefix) struct d_info *di; int prefix; { char c; if (d_next_char (di) != 'S') return NULL; c = d_next_char (di); if (c == '_' || IS_DIGIT (c) || IS_UPPER (c)) { int id; id = 0; if (c != '_') { do { if (IS_DIGIT (c)) id = id * 36 + c - '0'; else if (IS_UPPER (c)) id = id * 36 + c - 'A' + 10; else return NULL; c = d_next_char (di); } while (c != '_'); ++id; } if (id >= di->next_sub) return NULL; ++di->did_subs; return di->subs[id]; } else { int verbose; const struct d_standard_sub_info *p; const struct d_standard_sub_info *pend; verbose = (di->options & DMGL_VERBOSE) != 0; if (! verbose && prefix) { char peek; peek = d_peek_char (di); if (peek == 'C' || peek == 'D') verbose = 1; } pend = (&standard_subs[0] + sizeof standard_subs / sizeof standard_subs[0]); for (p = &standard_subs[0]; p < pend; ++p) { if (c == p->code) { const char *s; int len; if (p->set_last_name != NULL) di->last_name = d_make_sub (di, p->set_last_name, p->set_last_name_len); if (verbose) { s = p->full_expansion; len = p->full_len; } else { s = p->simple_expansion; len = p->simple_len; } di->expansion += len; return d_make_sub (di, s, len); } } return NULL; } } /* Resize the print buffer. */ static void d_print_resize (dpi, add) struct d_print_info *dpi; size_t add; { size_t need; if (dpi->buf == NULL) return; need = dpi->len + add; while (need > dpi->alc) { size_t newalc; char *newbuf; newalc = dpi->alc * 2; newbuf = realloc (dpi->buf, newalc); if (newbuf == NULL) { free (dpi->buf); dpi->buf = NULL; dpi->allocation_failure = 1; return; } dpi->buf = newbuf; dpi->alc = newalc; } } /* Append a character to the print buffer. */ static void d_print_append_char (dpi, c) struct d_print_info *dpi; int c; { if (dpi->buf != NULL) { if (dpi->len >= dpi->alc) { d_print_resize (dpi, 1); if (dpi->buf == NULL) return; } dpi->buf[dpi->len] = c; ++dpi->len; } } /* Append a buffer to the print buffer. */ static void d_print_append_buffer (dpi, s, l) struct d_print_info *dpi; const char *s; size_t l; { if (dpi->buf != NULL) { if (dpi->len + l > dpi->alc) { d_print_resize (dpi, l); if (dpi->buf == NULL) return; } memcpy (dpi->buf + dpi->len, s, l); dpi->len += l; } } /* Indicate that an error occurred during printing. */ static void d_print_error (dpi) struct d_print_info *dpi; { free (dpi->buf); dpi->buf = NULL; } /* Turn components into a human readable string. OPTIONS is the options bits passed to the demangler. DC is the tree to print. ESTIMATE is a guess at the length of the result. This returns a string allocated by malloc, or NULL on error. On success, this sets *PALC to the size of the allocated buffer. On failure, this sets *PALC to 0 for a bad parse, or to 1 for a memory allocation failure. */ CP_STATIC_IF_GLIBCPP_V3 char * cplus_demangle_print (options, dc, estimate, palc) int options; const struct demangle_component *dc; int estimate; size_t *palc; { struct d_print_info dpi; dpi.options = options; dpi.alc = estimate + 1; dpi.buf = malloc (dpi.alc); if (dpi.buf == NULL) { *palc = 1; return NULL; } dpi.len = 0; dpi.templates = NULL; dpi.modifiers = NULL; dpi.allocation_failure = 0; d_print_comp (&dpi, dc); d_append_char (&dpi, '\0'); if (dpi.buf != NULL) *palc = dpi.alc; else *palc = dpi.allocation_failure; return dpi.buf; } /* Subroutine to handle components. */ static void d_print_comp (dpi, dc) struct d_print_info *dpi; const struct demangle_component *dc; { if (dc == NULL) { d_print_error (dpi); return; } if (d_print_saw_error (dpi)) return; switch (dc->type) { case DEMANGLE_COMPONENT_NAME: if ((dpi->options & DMGL_JAVA) == 0) d_append_buffer (dpi, dc->u.s_name.s, dc->u.s_name.len); else d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len); return; case DEMANGLE_COMPONENT_QUAL_NAME: case DEMANGLE_COMPONENT_LOCAL_NAME: d_print_comp (dpi, d_left (dc)); if ((dpi->options & DMGL_JAVA) == 0) d_append_string_constant (dpi, "::"); else d_append_char (dpi, '.'); d_print_comp (dpi, d_right (dc)); return; case DEMANGLE_COMPONENT_TYPED_NAME: { struct d_print_mod *hold_modifiers; struct demangle_component *typed_name; struct d_print_mod adpm[4]; unsigned int i; struct d_print_template dpt; /* Pass the name down to the type so that it can be printed in the right place for the type. We also have to pass down any CV-qualifiers, which apply to the this parameter. */ hold_modifiers = dpi->modifiers; i = 0; typed_name = d_left (dc); while (typed_name != NULL) { if (i >= sizeof adpm / sizeof adpm[0]) { d_print_error (dpi); return; } adpm[i].next = dpi->modifiers; dpi->modifiers = &adpm[i]; adpm[i].mod = typed_name; adpm[i].printed = 0; adpm[i].templates = dpi->templates; ++i; if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS && typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS) break; typed_name = d_left (typed_name); } /* If typed_name is a template, then it applies to the function type as well. */ if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) { dpt.next = dpi->templates; dpi->templates = &dpt; dpt.template = typed_name; } /* If typed_name is a DEMANGLE_COMPONENT_LOCAL_NAME, then there may be CV-qualifiers on its right argument which really apply here; this happens when parsing a class which is local to a function. */ if (typed_name->type == DEMANGLE_COMPONENT_LOCAL_NAME) { struct demangle_component *local_name; local_name = d_right (typed_name); while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS || local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS || local_name->type == DEMANGLE_COMPONENT_CONST_THIS) { if (i >= sizeof adpm / sizeof adpm[0]) { d_print_error (dpi); return; } adpm[i] = adpm[i - 1]; adpm[i].next = &adpm[i - 1]; dpi->modifiers = &adpm[i]; adpm[i - 1].mod = local_name; adpm[i - 1].printed = 0; adpm[i - 1].templates = dpi->templates; ++i; local_name = d_left (local_name); } } d_print_comp (dpi, d_right (dc)); if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) dpi->templates = dpt.next; /* If the modifiers didn't get printed by the type, print them now. */ while (i > 0) { --i; if (! adpm[i].printed) { d_append_char (dpi, ' '); d_print_mod (dpi, adpm[i].mod); } } dpi->modifiers = hold_modifiers; return; } case DEMANGLE_COMPONENT_TEMPLATE: { struct d_print_mod *hold_dpm; /* Don't push modifiers into a template definition. Doing so could give the wrong definition for a template argument. Instead, treat the template essentially as a name. */ hold_dpm = dpi->modifiers; dpi->modifiers = NULL; d_print_comp (dpi, d_left (dc)); if (d_last_char (dpi) == '<') d_append_char (dpi, ' '); d_append_char (dpi, '<'); d_print_comp (dpi, d_right (dc)); /* Avoid generating two consecutive '>' characters, to avoid the C++ syntactic ambiguity. */ if (d_last_char (dpi) == '>') d_append_char (dpi, ' '); d_append_char (dpi, '>'); dpi->modifiers = hold_dpm; return; } case DEMANGLE_COMPONENT_TEMPLATE_PARAM: { long i; struct demangle_component *a; struct d_print_template *hold_dpt; if (dpi->templates == NULL) { d_print_error (dpi); return; } i = dc->u.s_number.number; for (a = d_right (dpi->templates->template); a != NULL; a = d_right (a)) { if (a->type != DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) { d_print_error (dpi); return; } if (i <= 0) break; --i; } if (i != 0 || a == NULL) { d_print_error (dpi); return; } /* While processing this parameter, we need to pop the list of templates. This is because the template parameter may itself be a reference to a parameter of an outer template. */ hold_dpt = dpi->templates; dpi->templates = hold_dpt->next; d_print_comp (dpi, d_left (a)); dpi->templates = hold_dpt; return; } case DEMANGLE_COMPONENT_CTOR: d_print_comp (dpi, dc->u.s_ctor.name); return; case DEMANGLE_COMPONENT_DTOR: d_append_char (dpi, '~'); d_print_comp (dpi, dc->u.s_dtor.name); return; case DEMANGLE_COMPONENT_VTABLE: d_append_string_constant (dpi, "vtable for "); d_print_comp (dpi, d_left (dc)); return; case DEMANGLE_COMPONENT_VTT: d_append_string_constant (dpi, "VTT for "); d_print_comp (dpi, d_left (dc)); return; case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: d_append_string_constant (dpi, "construction vtable for "); d_print_comp (dpi, d_left (dc)); d_append_string_constant (dpi, "-in-"); d_print_comp (dpi, d_right (dc)); return; case DEMANGLE_COMPONENT_TYPEINFO: d_append_string_constant (dpi, "typeinfo for "); d_print_comp (dpi, d_left (dc)); return; case DEMANGLE_COMPONENT_TYPEINFO_NAME: d_append_string_constant (dpi, "typeinfo name for "); d_print_comp (dpi, d_left (dc)); return; case DEMANGLE_COMPONENT_TYPEINFO_FN: d_append_string_constant (dpi, "typeinfo fn for "); d_print_comp (dpi, d_left (dc)); return; case DEMANGLE_COMPONENT_THUNK: d_append_string_constant (dpi, "non-virtual thunk to "); d_print_comp (dpi, d_left (dc)); return; case DEMANGLE_COMPONENT_VIRTUAL_THUNK: d_append_string_constant (dpi, "virtual thunk to "); d_print_comp (dpi, d_left (dc)); return; case DEMANGLE_COMPONENT_COVARIANT_THUNK: d_append_string_constant (dpi, "covariant return thunk to "); d_print_comp (dpi, d_left (dc)); return; case DEMANGLE_COMPONENT_JAVA_CLASS: d_append_string_constant (dpi, "java Class for "); d_print_comp (dpi, d_left (dc)); return; case DEMANGLE_COMPONENT_GUARD: d_append_string_constant (dpi, "guard variable for "); d_print_comp (dpi, d_left (dc)); return; case DEMANGLE_COMPONENT_REFTEMP: d_append_string_constant (dpi, "reference temporary for "); d_print_comp (dpi, d_left (dc)); return; case DEMANGLE_COMPONENT_SUB_STD: d_append_buffer (dpi, dc->u.s_string.string, dc->u.s_string.len); return; case DEMANGLE_COMPONENT_RESTRICT: case DEMANGLE_COMPONENT_VOLATILE: case DEMANGLE_COMPONENT_CONST: { struct d_print_mod *pdpm; /* When printing arrays, it's possible to have cases where the same CV-qualifier gets pushed on the stack multiple times. We only need to print it once. */ for (pdpm = dpi->modifiers; pdpm != NULL; pdpm = pdpm->next) { if (! pdpm->printed) { if (pdpm->mod->type != DEMANGLE_COMPONENT_RESTRICT && pdpm->mod->type != DEMANGLE_COMPONENT_VOLATILE && pdpm->mod->type != DEMANGLE_COMPONENT_CONST) break; if (pdpm->mod->type == dc->type) { d_print_comp (dpi, d_left (dc)); return; } } } } /* Fall through. */ case DEMANGLE_COMPONENT_RESTRICT_THIS: case DEMANGLE_COMPONENT_VOLATILE_THIS: case DEMANGLE_COMPONENT_CONST_THIS: case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_REFERENCE: case DEMANGLE_COMPONENT_COMPLEX: case DEMANGLE_COMPONENT_IMAGINARY: { /* We keep a list of modifiers on the stack. */ struct d_print_mod dpm; dpm.next = dpi->modifiers; dpi->modifiers = &dpm; dpm.mod = dc; dpm.printed = 0; dpm.templates = dpi->templates; d_print_comp (dpi, d_left (dc)); /* If the modifier didn't get printed by the type, print it now. */ if (! dpm.printed) d_print_mod (dpi, dc); dpi->modifiers = dpm.next; return; } case DEMANGLE_COMPONENT_BUILTIN_TYPE: if ((dpi->options & DMGL_JAVA) == 0) d_append_buffer (dpi, dc->u.s_builtin.type->name, dc->u.s_builtin.type->len); else d_append_buffer (dpi, dc->u.s_builtin.type->java_name, dc->u.s_builtin.type->java_len); return; case DEMANGLE_COMPONENT_VENDOR_TYPE: d_print_comp (dpi, d_left (dc)); return; case DEMANGLE_COMPONENT_FUNCTION_TYPE: { if (d_left (dc) != NULL) { struct d_print_mod dpm; /* We must pass this type down as a modifier in order to print it in the right location. */ dpm.next = dpi->modifiers; dpi->modifiers = &dpm; dpm.mod = dc; dpm.printed = 0; dpm.templates = dpi->templates; d_print_comp (dpi, d_left (dc)); dpi->modifiers = dpm.next; if (dpm.printed) return; d_append_char (dpi, ' '); } d_print_function_type (dpi, dc, dpi->modifiers); return; } case DEMANGLE_COMPONENT_ARRAY_TYPE: { struct d_print_mod *hold_modifiers; struct d_print_mod adpm[4]; unsigned int i; struct d_print_mod *pdpm; /* We must pass this type down as a modifier in order to print multi-dimensional arrays correctly. If the array itself is CV-qualified, we act as though the element type were CV-qualified. We do this by copying the modifiers down rather than fiddling pointers, so that we don't wind up with a d_print_mod higher on the stack pointing into our stack frame after we return. */ hold_modifiers = dpi->modifiers; adpm[0].next = hold_modifiers; dpi->modifiers = &adpm[0]; adpm[0].mod = dc; adpm[0].printed = 0; adpm[0].templates = dpi->templates; i = 1; pdpm = hold_modifiers; while (pdpm != NULL && (pdpm->mod->type == DEMANGLE_COMPONENT_RESTRICT || pdpm->mod->type == DEMANGLE_COMPONENT_VOLATILE || pdpm->mod->type == DEMANGLE_COMPONENT_CONST)) { if (! pdpm->printed) { if (i >= sizeof adpm / sizeof adpm[0]) { d_print_error (dpi); return; } adpm[i] = *pdpm; adpm[i].next = dpi->modifiers; dpi->modifiers = &adpm[i]; pdpm->printed = 1; ++i; } pdpm = pdpm->next; } d_print_comp (dpi, d_right (dc)); dpi->modifiers = hold_modifiers; if (adpm[0].printed) return; while (i > 1) { --i; d_print_mod (dpi, adpm[i].mod); } d_print_array_type (dpi, dc, dpi->modifiers); return; } case DEMANGLE_COMPONENT_PTRMEM_TYPE: { struct d_print_mod dpm; dpm.next = dpi->modifiers; dpi->modifiers = &dpm; dpm.mod = dc; dpm.printed = 0; dpm.templates = dpi->templates; d_print_comp (dpi, d_right (dc)); /* If the modifier didn't get printed by the type, print it now. */ if (! dpm.printed) { d_append_char (dpi, ' '); d_print_comp (dpi, d_left (dc)); d_append_string_constant (dpi, "::*"); } dpi->modifiers = dpm.next; return; } case DEMANGLE_COMPONENT_ARGLIST: case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: d_print_comp (dpi, d_left (dc)); if (d_right (dc) != NULL) { d_append_string_constant (dpi, ", "); d_print_comp (dpi, d_right (dc)); } return; case DEMANGLE_COMPONENT_OPERATOR: { char c; d_append_string_constant (dpi, "operator"); c = dc->u.s_operator.op->name[0]; if (IS_LOWER (c)) d_append_char (dpi, ' '); d_append_buffer (dpi, dc->u.s_operator.op->name, dc->u.s_operator.op->len); return; } case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: d_append_string_constant (dpi, "operator "); d_print_comp (dpi, dc->u.s_extended_operator.name); return; case DEMANGLE_COMPONENT_CAST: d_append_string_constant (dpi, "operator "); d_print_cast (dpi, dc); return; case DEMANGLE_COMPONENT_UNARY: if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST) d_print_expr_op (dpi, d_left (dc)); else { d_append_char (dpi, '('); d_print_cast (dpi, d_left (dc)); d_append_char (dpi, ')'); } d_append_char (dpi, '('); d_print_comp (dpi, d_right (dc)); d_append_char (dpi, ')'); return; case DEMANGLE_COMPONENT_BINARY: if (d_right (dc)->type != DEMANGLE_COMPONENT_BINARY_ARGS) { d_print_error (dpi); return; } /* We wrap an expression which uses the greater-than operator in an extra layer of parens so that it does not get confused with the '>' which ends the template parameters. */ if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR && d_left (dc)->u.s_operator.op->len == 1 && d_left (dc)->u.s_operator.op->name[0] == '>') d_append_char (dpi, '('); d_append_char (dpi, '('); d_print_comp (dpi, d_left (d_right (dc))); d_append_string_constant (dpi, ") "); d_print_expr_op (dpi, d_left (dc)); d_append_string_constant (dpi, " ("); d_print_comp (dpi, d_right (d_right (dc))); d_append_char (dpi, ')'); if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR && d_left (dc)->u.s_operator.op->len == 1 && d_left (dc)->u.s_operator.op->name[0] == '>') d_append_char (dpi, ')'); return; case DEMANGLE_COMPONENT_BINARY_ARGS: /* We should only see this as part of DEMANGLE_COMPONENT_BINARY. */ d_print_error (dpi); return; case DEMANGLE_COMPONENT_TRINARY: if (d_right (dc)->type != DEMANGLE_COMPONENT_TRINARY_ARG1 || d_right (d_right (dc))->type != DEMANGLE_COMPONENT_TRINARY_ARG2) { d_print_error (dpi); return; } d_append_char (dpi, '('); d_print_comp (dpi, d_left (d_right (dc))); d_append_string_constant (dpi, ") "); d_print_expr_op (dpi, d_left (dc)); d_append_string_constant (dpi, " ("); d_print_comp (dpi, d_left (d_right (d_right (dc)))); d_append_string_constant (dpi, ") : ("); d_print_comp (dpi, d_right (d_right (d_right (dc)))); d_append_char (dpi, ')'); return; case DEMANGLE_COMPONENT_TRINARY_ARG1: case DEMANGLE_COMPONENT_TRINARY_ARG2: /* We should only see these are part of DEMANGLE_COMPONENT_TRINARY. */ d_print_error (dpi); return; case DEMANGLE_COMPONENT_LITERAL: case DEMANGLE_COMPONENT_LITERAL_NEG: { enum d_builtin_type_print tp; /* For some builtin types, produce simpler output. */ tp = D_PRINT_DEFAULT; if (d_left (dc)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE) { tp = d_left (dc)->u.s_builtin.type->print; switch (tp) { case D_PRINT_INT: case D_PRINT_UNSIGNED: case D_PRINT_LONG: case D_PRINT_UNSIGNED_LONG: case D_PRINT_LONG_LONG: case D_PRINT_UNSIGNED_LONG_LONG: if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME) { if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG) d_append_char (dpi, '-'); d_print_comp (dpi, d_right (dc)); switch (tp) { default: break; case D_PRINT_UNSIGNED: d_append_char (dpi, 'u'); break; case D_PRINT_LONG: d_append_char (dpi, 'l'); break; case D_PRINT_UNSIGNED_LONG: d_append_string_constant (dpi, "ul"); break; case D_PRINT_LONG_LONG: d_append_string_constant (dpi, "ll"); break; case D_PRINT_UNSIGNED_LONG_LONG: d_append_string_constant (dpi, "ull"); break; } return; } break; case D_PRINT_BOOL: if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME && d_right (dc)->u.s_name.len == 1 && dc->type == DEMANGLE_COMPONENT_LITERAL) { switch (d_right (dc)->u.s_name.s[0]) { case '0': d_append_string_constant (dpi, "false"); return; case '1': d_append_string_constant (dpi, "true"); return; default: break; } } break; default: break; } } d_append_char (dpi, '('); d_print_comp (dpi, d_left (dc)); d_append_char (dpi, ')'); if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG) d_append_char (dpi, '-'); if (tp == D_PRINT_FLOAT) d_append_char (dpi, '['); d_print_comp (dpi, d_right (dc)); if (tp == D_PRINT_FLOAT) d_append_char (dpi, ']'); } return; default: d_print_error (dpi); return; } } /* Print a Java dentifier. For Java we try to handle encoded extended Unicode characters. The C++ ABI doesn't mention Unicode encoding, so we don't it for C++. Characters are encoded as __U+_. */ static void d_print_java_identifier (dpi, name, len) struct d_print_info *dpi; const char *name; int len; { const char *p; const char *end; end = name + len; for (p = name; p < end; ++p) { if (end - p > 3 && p[0] == '_' && p[1] == '_' && p[2] == 'U') { unsigned long c; const char *q; c = 0; for (q = p + 3; q < end; ++q) { int dig; if (IS_DIGIT (*q)) dig = *q - '0'; else if (*q >= 'A' && *q <= 'F') dig = *q - 'A' + 10; else if (*q >= 'a' && *q <= 'f') dig = *q - 'a' + 10; else break; c = c * 16 + dig; } /* If the Unicode character is larger than 256, we don't try to deal with it here. FIXME. */ if (q < end && *q == '_' && c < 256) { d_append_char (dpi, c); p = q; continue; } } d_append_char (dpi, *p); } } /* Print a list of modifiers. SUFFIX is 1 if we are printing qualifiers on this after printing a function. */ static void d_print_mod_list (dpi, mods, suffix) struct d_print_info *dpi; struct d_print_mod *mods; int suffix; { struct d_print_template *hold_dpt; if (mods == NULL || d_print_saw_error (dpi)) return; if (mods->printed || (! suffix && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS))) { d_print_mod_list (dpi, mods->next, suffix); return; } mods->printed = 1; hold_dpt = dpi->templates; dpi->templates = mods->templates; if (mods->mod->type == DEMANGLE_COMPONENT_FUNCTION_TYPE) { d_print_function_type (dpi, mods->mod, mods->next); dpi->templates = hold_dpt; return; } else if (mods->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE) { d_print_array_type (dpi, mods->mod, mods->next); dpi->templates = hold_dpt; return; } else if (mods->mod->type == DEMANGLE_COMPONENT_LOCAL_NAME) { struct d_print_mod *hold_modifiers; struct demangle_component *dc; /* When this is on the modifier stack, we have pulled any qualifiers off the right argument already. Otherwise, we print it as usual, but don't let the left argument see any modifiers. */ hold_modifiers = dpi->modifiers; dpi->modifiers = NULL; d_print_comp (dpi, d_left (mods->mod)); dpi->modifiers = hold_modifiers; if ((dpi->options & DMGL_JAVA) == 0) d_append_string_constant (dpi, "::"); else d_append_char (dpi, '.'); dc = d_right (mods->mod); while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS || dc->type == DEMANGLE_COMPONENT_CONST_THIS) dc = d_left (dc); d_print_comp (dpi, dc); dpi->templates = hold_dpt; return; } d_print_mod (dpi, mods->mod); dpi->templates = hold_dpt; d_print_mod_list (dpi, mods->next, suffix); } /* Print a modifier. */ static void d_print_mod (dpi, mod) struct d_print_info *dpi; const struct demangle_component *mod; { switch (mod->type) { case DEMANGLE_COMPONENT_RESTRICT: case DEMANGLE_COMPONENT_RESTRICT_THIS: d_append_string_constant (dpi, " restrict"); return; case DEMANGLE_COMPONENT_VOLATILE: case DEMANGLE_COMPONENT_VOLATILE_THIS: d_append_string_constant (dpi, " volatile"); return; case DEMANGLE_COMPONENT_CONST: case DEMANGLE_COMPONENT_CONST_THIS: d_append_string_constant (dpi, " const"); return; case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: d_append_char (dpi, ' '); d_print_comp (dpi, d_right (mod)); return; case DEMANGLE_COMPONENT_POINTER: /* There is no pointer symbol in Java. */ if ((dpi->options & DMGL_JAVA) == 0) d_append_char (dpi, '*'); return; case DEMANGLE_COMPONENT_REFERENCE: d_append_char (dpi, '&'); return; case DEMANGLE_COMPONENT_COMPLEX: d_append_string_constant (dpi, "complex "); return; case DEMANGLE_COMPONENT_IMAGINARY: d_append_string_constant (dpi, "imaginary "); return; case DEMANGLE_COMPONENT_PTRMEM_TYPE: if (d_last_char (dpi) != '(') d_append_char (dpi, ' '); d_print_comp (dpi, d_left (mod)); d_append_string_constant (dpi, "::*"); return; case DEMANGLE_COMPONENT_TYPED_NAME: d_print_comp (dpi, d_left (mod)); return; default: /* Otherwise, we have something that won't go back on the modifier stack, so we can just print it. */ d_print_comp (dpi, mod); return; } } /* Print a function type, except for the return type. */ static void d_print_function_type (dpi, dc, mods) struct d_print_info *dpi; const struct demangle_component *dc; struct d_print_mod *mods; { int need_paren; int saw_mod; int need_space; struct d_print_mod *p; struct d_print_mod *hold_modifiers; need_paren = 0; saw_mod = 0; need_space = 0; for (p = mods; p != NULL; p = p->next) { if (p->printed) break; saw_mod = 1; switch (p->mod->type) { case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_REFERENCE: need_paren = 1; break; case DEMANGLE_COMPONENT_RESTRICT: case DEMANGLE_COMPONENT_VOLATILE: case DEMANGLE_COMPONENT_CONST: case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: case DEMANGLE_COMPONENT_COMPLEX: case DEMANGLE_COMPONENT_IMAGINARY: case DEMANGLE_COMPONENT_PTRMEM_TYPE: need_space = 1; need_paren = 1; break; case DEMANGLE_COMPONENT_RESTRICT_THIS: case DEMANGLE_COMPONENT_VOLATILE_THIS: case DEMANGLE_COMPONENT_CONST_THIS: break; default: break; } if (need_paren) break; } if (d_left (dc) != NULL && ! saw_mod) need_paren = 1; if (need_paren) { if (! need_space) { if (d_last_char (dpi) != '(' && d_last_char (dpi) != '*') need_space = 1; } if (need_space && d_last_char (dpi) != ' ') d_append_char (dpi, ' '); d_append_char (dpi, '('); } hold_modifiers = dpi->modifiers; dpi->modifiers = NULL; d_print_mod_list (dpi, mods, 0); if (need_paren) d_append_char (dpi, ')'); d_append_char (dpi, '('); if (d_right (dc) != NULL) d_print_comp (dpi, d_right (dc)); d_append_char (dpi, ')'); d_print_mod_list (dpi, mods, 1); dpi->modifiers = hold_modifiers; } /* Print an array type, except for the element type. */ static void d_print_array_type (dpi, dc, mods) struct d_print_info *dpi; const struct demangle_component *dc; struct d_print_mod *mods; { int need_space; need_space = 1; if (mods != NULL) { int need_paren; struct d_print_mod *p; need_paren = 0; for (p = mods; p != NULL; p = p->next) { if (! p->printed) { if (p->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE) { need_space = 0; break; } else { need_paren = 1; need_space = 1; break; } } } if (need_paren) d_append_string_constant (dpi, " ("); d_print_mod_list (dpi, mods, 0); if (need_paren) d_append_char (dpi, ')'); } if (need_space) d_append_char (dpi, ' '); d_append_char (dpi, '['); if (d_left (dc) != NULL) d_print_comp (dpi, d_left (dc)); d_append_char (dpi, ']'); } /* Print an operator in an expression. */ static void d_print_expr_op (dpi, dc) struct d_print_info *dpi; const struct demangle_component *dc; { if (dc->type == DEMANGLE_COMPONENT_OPERATOR) d_append_buffer (dpi, dc->u.s_operator.op->name, dc->u.s_operator.op->len); else d_print_comp (dpi, dc); } /* Print a cast. */ static void d_print_cast (dpi, dc) struct d_print_info *dpi; const struct demangle_component *dc; { if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE) d_print_comp (dpi, d_left (dc)); else { struct d_print_mod *hold_dpm; struct d_print_template dpt; /* It appears that for a templated cast operator, we need to put the template parameters in scope for the operator name, but not for the parameters. The effect is that we need to handle the template printing here. */ hold_dpm = dpi->modifiers; dpi->modifiers = NULL; dpt.next = dpi->templates; dpi->templates = &dpt; dpt.template = d_left (dc); d_print_comp (dpi, d_left (d_left (dc))); dpi->templates = dpt.next; if (d_last_char (dpi) == '<') d_append_char (dpi, ' '); d_append_char (dpi, '<'); d_print_comp (dpi, d_right (d_left (dc))); /* Avoid generating two consecutive '>' characters, to avoid the C++ syntactic ambiguity. */ if (d_last_char (dpi) == '>') d_append_char (dpi, ' '); d_append_char (dpi, '>'); dpi->modifiers = hold_dpm; } } /* Initialize the information structure we use to pass around information. */ CP_STATIC_IF_GLIBCPP_V3 void cplus_demangle_init_info (mangled, options, len, di) const char *mangled; int options; size_t len; struct d_info *di; { di->s = mangled; di->send = mangled + len; di->options = options; di->n = mangled; /* We can not need more components than twice the number of chars in the mangled string. Most components correspond directly to chars, but the ARGLIST types are exceptions. */ di->num_comps = 2 * len; di->next_comp = 0; /* Similarly, we can not need more substitutions than there are chars in the mangled string. */ di->num_subs = len; di->next_sub = 0; di->did_subs = 0; di->last_name = NULL; di->expansion = 0; } /* Entry point for the demangler. If MANGLED is a g++ v3 ABI mangled name, return a buffer allocated with malloc holding the demangled name. OPTIONS is the usual libiberty demangler options. On success, this sets *PALC to the allocated size of the returned buffer. On failure, this sets *PALC to 0 for a bad name, or 1 for a memory allocation failure. On failure, this returns NULL. */ static char * d_demangle (mangled, options, palc) const char* mangled; int options; size_t *palc; { size_t len; int type; struct d_info di; struct demangle_component *dc; int estimate; char *ret; *palc = 0; len = strlen (mangled); if (mangled[0] == '_' && mangled[1] == 'Z') type = 0; else if (strncmp (mangled, "_GLOBAL_", 8) == 0 && (mangled[8] == '.' || mangled[8] == '_' || mangled[8] == '$') && (mangled[9] == 'D' || mangled[9] == 'I') && mangled[10] == '_') { char *r; r = malloc (40 + len - 11); if (r == NULL) *palc = 1; else { if (mangled[9] == 'I') strcpy (r, "global constructors keyed to "); else strcpy (r, "global destructors keyed to "); strcat (r, mangled + 11); } return r; } else { if ((options & DMGL_TYPES) == 0) return NULL; type = 1; } cplus_demangle_init_info (mangled, options, len, &di); { #ifdef CP_DYNAMIC_ARRAYS __extension__ struct demangle_component comps[di.num_comps]; __extension__ struct demangle_component *subs[di.num_subs]; di.comps = &comps[0]; di.subs = &subs[0]; #else di.comps = ((struct demangle_component *) malloc (di.num_comps * sizeof (struct demangle_component))); di.subs = ((struct demangle_component **) malloc (di.num_subs * sizeof (struct demangle_component *))); if (di.comps == NULL || di.subs == NULL) { if (di.comps != NULL) free (di.comps); if (di.subs != NULL) free (di.subs); *palc = 1; return NULL; } #endif if (! type) dc = cplus_demangle_mangled_name (&di, 1); else dc = cplus_demangle_type (&di); /* If DMGL_PARAMS is set, then if we didn't consume the entire mangled string, then we didn't successfully demangle it. If DMGL_PARAMS is not set, we didn't look at the trailing parameters. */ if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0') dc = NULL; #ifdef CP_DEMANGLE_DEBUG if (dc == NULL) printf ("failed demangling\n"); else d_dump (dc, 0); #endif /* We try to guess the length of the demangled string, to minimize calls to realloc during demangling. */ estimate = len + di.expansion + 10 * di.did_subs; estimate += estimate / 8; ret = NULL; if (dc != NULL) ret = cplus_demangle_print (options, dc, estimate, palc); #ifndef CP_DYNAMIC_ARRAYS free (di.comps); free (di.subs); #endif #ifdef CP_DEMANGLE_DEBUG if (ret != NULL) { int rlen; rlen = strlen (ret); if (rlen > 2 * estimate) printf ("*** Length %d much greater than estimate %d\n", rlen, estimate); else if (rlen > estimate) printf ("*** Length %d greater than estimate %d\n", rlen, estimate); else if (rlen < estimate / 2) printf ("*** Length %d much less than estimate %d\n", rlen, estimate); } #endif } return ret; } static char * cplus_demangle_v3 (mangled, options) const char* mangled; int options; { size_t alc; return d_demangle (mangled, options, &alc); } /* Demangle a Java symbol. Java uses a subset of the V3 ABI C++ mangling conventions, but the output formatting is a little different. This instructs the C++ demangler not to emit pointer characters ("*"), and to use Java's namespace separator symbol ("." instead of "::"). It then does an additional pass over the demangled output to replace instances of JArray with TYPE[]. */ static char * java_demangle_v3 (mangled) const char* mangled; { size_t alc; char *demangled; int nesting; char *from; char *to; demangled = d_demangle (mangled, DMGL_JAVA | DMGL_PARAMS, &alc); if (demangled == NULL) return NULL; nesting = 0; from = demangled; to = from; while (*from != '\0') { if (strncmp (from, "JArray<", 7) == 0) { from += 7; ++nesting; } else if (nesting > 0 && *from == '>') { while (to > demangled && to[-1] == ' ') --to; *to++ = '['; *to++ = ']'; --nesting; ++from; } else *to++ = *from++; } *to = '\0'; return demangled; } #ifndef IN_GLIBCPP_V3 /* Demangle a string in order to find out whether it is a constructor or destructor. Return non-zero on success. Set *CTOR_KIND and *DTOR_KIND appropriately. */ static int is_ctor_or_dtor (mangled, ctor_kind, dtor_kind) const char *mangled; enum gnu_v3_ctor_kinds *ctor_kind; enum gnu_v3_dtor_kinds *dtor_kind; { struct d_info di; struct demangle_component *dc; int ret; *ctor_kind = (enum gnu_v3_ctor_kinds) 0; *dtor_kind = (enum gnu_v3_dtor_kinds) 0; cplus_demangle_init_info (mangled, DMGL_GNU_V3, strlen (mangled), &di); { #ifdef CP_DYNAMIC_ARRAYS __extension__ struct demangle_component comps[di.num_comps]; __extension__ struct demangle_component *subs[di.num_subs]; di.comps = &comps[0]; di.subs = &subs[0]; #else di.comps = ((struct demangle_component *) malloc (di.num_comps * sizeof (struct demangle_component))); di.subs = ((struct demangle_component **) malloc (di.num_subs * sizeof (struct demangle_component *))); if (di.comps == NULL || di.subs == NULL) { if (di.comps != NULL) free (di.comps); if (di.subs != NULL) free (di.subs); return 0; } #endif dc = cplus_demangle_mangled_name (&di, 1); /* Note that because we did not pass DMGL_PARAMS, we don't expect to demangle the entire string. */ ret = 0; while (dc != NULL) { switch (dc->type) { default: dc = NULL; break; case DEMANGLE_COMPONENT_TYPED_NAME: case DEMANGLE_COMPONENT_TEMPLATE: case DEMANGLE_COMPONENT_RESTRICT_THIS: case DEMANGLE_COMPONENT_VOLATILE_THIS: case DEMANGLE_COMPONENT_CONST_THIS: dc = d_left (dc); break; case DEMANGLE_COMPONENT_QUAL_NAME: case DEMANGLE_COMPONENT_LOCAL_NAME: dc = d_right (dc); break; case DEMANGLE_COMPONENT_CTOR: *ctor_kind = dc->u.s_ctor.kind; ret = 1; dc = NULL; break; case DEMANGLE_COMPONENT_DTOR: *dtor_kind = dc->u.s_dtor.kind; ret = 1; dc = NULL; break; } } #ifndef CP_DYNAMIC_ARRAYS free (di.subs); free (di.comps); #endif } return ret; } /* Return whether NAME is the mangled form of a g++ V3 ABI constructor name. A non-zero return indicates the type of constructor. */ enum gnu_v3_ctor_kinds is_gnu_v3_mangled_ctor (name) const char *name; { enum gnu_v3_ctor_kinds ctor_kind; enum gnu_v3_dtor_kinds dtor_kind; if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind)) return (enum gnu_v3_ctor_kinds) 0; return ctor_kind; } /* Return whether NAME is the mangled form of a g++ V3 ABI destructor name. A non-zero return indicates the type of destructor. */ enum gnu_v3_dtor_kinds is_gnu_v3_mangled_dtor (name) const char *name; { enum gnu_v3_ctor_kinds ctor_kind; enum gnu_v3_dtor_kinds dtor_kind; if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind)) return (enum gnu_v3_dtor_kinds) 0; return dtor_kind; } #endif /* IN_GLIBCPP_V3 */ /* Demangler for GNU C++ Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.uucp) Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling Modified by Satish Pai (pai@apollo.hp.com) for HP demangling This file is part of the libiberty library. Libiberty is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. In addition to the permissions in the GNU Library General Public License, the Free Software Foundation gives you unlimited permission to link the compiled version of this file into combinations with other programs, and to distribute those combinations without any restriction coming from the use of this file. (The Library Public License restrictions do apply in other respects; for example, they cover modification of the file, and distribution when not linked into a combined executable.) Libiberty is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with libiberty; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file exports two functions; cplus_mangle_opname and cplus_demangle. This file imports xmalloc and g_realloc, which are like malloc and realloc except that they generate a fatal error if there is no available memory. */ /* This file lives in both GCC and libiberty. When making changes, please try not to break either. */ #undef CURRENT_DEMANGLING_STYLE #define CURRENT_DEMANGLING_STYLE work->options static char *ada_demangle PARAMS ((const char *, int)); #define min(X,Y) (((X) < (Y)) ? (X) : (Y)) /* A value at least one greater than the maximum number of characters that will be output when using the `%d' format with `printf'. */ #define INTBUF_SIZE 32 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN; /* In order to allow a single demangler executable to demangle strings using various common values of CPLUS_MARKER, as well as any specific one set at compile time, we maintain a string containing all the commonly used ones, and check to see if the marker we are looking for is in that string. CPLUS_MARKER is usually '$' on systems where the assembler can deal with that. Where the assembler can't, it's usually '.' (but on many systems '.' is used for other things). We put the current defined CPLUS_MARKER first (which defaults to '$'), followed by the next most common value, followed by an explicit '$' in case the value of CPLUS_MARKER is not '$'. We could avoid this if we could just get g++ to tell us what the actual cplus marker character is as part of the debug information, perhaps by ensuring that it is the character that terminates the gcc_compiled marker symbol (FIXME). */ #if !defined (CPLUS_MARKER) #define CPLUS_MARKER '$' #endif static enum demangling_styles current_demangling_style = auto_demangling; static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' }; static char char_str[2] = { '\000', '\000' }; typedef struct string /* Beware: these aren't required to be */ { /* '\0' terminated. */ char *b; /* pointer to start of string */ char *p; /* pointer after last character */ char *e; /* pointer after end of allocated space */ } string; /* Stuff that is shared between sub-routines. Using a shared structure allows cplus_demangle to be reentrant. */ struct work_stuff { int options; char **typevec; char **ktypevec; char **btypevec; int numk; int numb; int ksize; int bsize; int ntypes; int typevec_size; int constructor; int destructor; int static_type; /* A static member function */ int temp_start; /* index in demangled to start of template args */ int type_quals; /* The type qualifiers. */ int dllimported; /* Symbol imported from a PE DLL */ char **tmpl_argvec; /* Template function arguments. */ int ntmpl_args; /* The number of template function arguments. */ int forgetting_types; /* Nonzero if we are not remembering the types we see. */ string* previous_argument; /* The last function argument demangled. */ int nrepeats; /* The number of times to repeat the previous argument. */ }; #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI) #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS) static const struct optable { const char *const in; const char *const out; const int flags; } optable[] = { {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */ {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */ {"new", " new", 0}, /* old (1.91, and 1.x) */ {"delete", " delete", 0}, /* old (1.91, and 1.x) */ {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */ {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */ {"as", "=", DMGL_ANSI}, /* ansi */ {"ne", "!=", DMGL_ANSI}, /* old, ansi */ {"eq", "==", DMGL_ANSI}, /* old, ansi */ {"ge", ">=", DMGL_ANSI}, /* old, ansi */ {"gt", ">", DMGL_ANSI}, /* old, ansi */ {"le", "<=", DMGL_ANSI}, /* old, ansi */ {"lt", "<", DMGL_ANSI}, /* old, ansi */ {"plus", "+", 0}, /* old */ {"pl", "+", DMGL_ANSI}, /* ansi */ {"apl", "+=", DMGL_ANSI}, /* ansi */ {"minus", "-", 0}, /* old */ {"mi", "-", DMGL_ANSI}, /* ansi */ {"ami", "-=", DMGL_ANSI}, /* ansi */ {"mult", "*", 0}, /* old */ {"ml", "*", DMGL_ANSI}, /* ansi */ {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */ {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */ {"convert", "+", 0}, /* old (unary +) */ {"negate", "-", 0}, /* old (unary -) */ {"trunc_mod", "%", 0}, /* old */ {"md", "%", DMGL_ANSI}, /* ansi */ {"amd", "%=", DMGL_ANSI}, /* ansi */ {"trunc_div", "/", 0}, /* old */ {"dv", "/", DMGL_ANSI}, /* ansi */ {"adv", "/=", DMGL_ANSI}, /* ansi */ {"truth_andif", "&&", 0}, /* old */ {"aa", "&&", DMGL_ANSI}, /* ansi */ {"truth_orif", "||", 0}, /* old */ {"oo", "||", DMGL_ANSI}, /* ansi */ {"truth_not", "!", 0}, /* old */ {"nt", "!", DMGL_ANSI}, /* ansi */ {"postincrement","++", 0}, /* old */ {"pp", "++", DMGL_ANSI}, /* ansi */ {"postdecrement","--", 0}, /* old */ {"mm", "--", DMGL_ANSI}, /* ansi */ {"bit_ior", "|", 0}, /* old */ {"or", "|", DMGL_ANSI}, /* ansi */ {"aor", "|=", DMGL_ANSI}, /* ansi */ {"bit_xor", "^", 0}, /* old */ {"er", "^", DMGL_ANSI}, /* ansi */ {"aer", "^=", DMGL_ANSI}, /* ansi */ {"bit_and", "&", 0}, /* old */ {"ad", "&", DMGL_ANSI}, /* ansi */ {"aad", "&=", DMGL_ANSI}, /* ansi */ {"bit_not", "~", 0}, /* old */ {"co", "~", DMGL_ANSI}, /* ansi */ {"call", "()", 0}, /* old */ {"cl", "()", DMGL_ANSI}, /* ansi */ {"alshift", "<<", 0}, /* old */ {"ls", "<<", DMGL_ANSI}, /* ansi */ {"als", "<<=", DMGL_ANSI}, /* ansi */ {"arshift", ">>", 0}, /* old */ {"rs", ">>", DMGL_ANSI}, /* ansi */ {"ars", ">>=", DMGL_ANSI}, /* ansi */ {"component", "->", 0}, /* old */ {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */ {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */ {"indirect", "*", 0}, /* old */ {"method_call", "->()", 0}, /* old */ {"addr", "&", 0}, /* old (unary &) */ {"array", "[]", 0}, /* old */ {"vc", "[]", DMGL_ANSI}, /* ansi */ {"compound", ", ", 0}, /* old */ {"cm", ", ", DMGL_ANSI}, /* ansi */ {"cond", "?:", 0}, /* old */ {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */ {"max", ">?", 0}, /* old */ {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */ {"min", "*", DMGL_ANSI}, /* ansi */ {"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */ }; /* These values are used to indicate the various type varieties. They are all non-zero so that they can be used as `success' values. */ typedef enum type_kind_t { tk_none, tk_pointer, tk_reference, tk_integral, tk_bool, tk_char, tk_real } type_kind_t; static const struct demangler_engine libiberty_demanglers[] = { { NO_DEMANGLING_STYLE_STRING, no_demangling, "Demangling disabled" } , { AUTO_DEMANGLING_STYLE_STRING, auto_demangling, "Automatic selection based on executable" } , { GNU_DEMANGLING_STYLE_STRING, gnu_demangling, "GNU (g++) style demangling" } , { LUCID_DEMANGLING_STYLE_STRING, lucid_demangling, "Lucid (lcc) style demangling" } , { ARM_DEMANGLING_STYLE_STRING, arm_demangling, "ARM style demangling" } , { HP_DEMANGLING_STYLE_STRING, hp_demangling, "HP (aCC) style demangling" } , { EDG_DEMANGLING_STYLE_STRING, edg_demangling, "EDG style demangling" } , { GNU_V3_DEMANGLING_STYLE_STRING, gnu_v3_demangling, "GNU (g++) V3 ABI-style demangling" } , { JAVA_DEMANGLING_STYLE_STRING, java_demangling, "Java style demangling" } , { GNAT_DEMANGLING_STYLE_STRING, gnat_demangling, "GNAT style demangling" } , { NULL, unknown_demangling, NULL } }; #define STRING_EMPTY(str) ((str) -> b == (str) -> p) #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ string_append(str, " ");} #define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b)) /* The scope separator appropriate for the language being demangled. */ #define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::") #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */ #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */ /* Prototypes for local functions */ static void delete_work_stuff PARAMS ((struct work_stuff *)); static void delete_non_B_K_work_stuff PARAMS ((struct work_stuff *)); static char * mop_up PARAMS ((struct work_stuff *, string *, int)); static void squangle_mop_up PARAMS ((struct work_stuff *)); static void work_stuff_copy_to_from PARAMS ((struct work_stuff *, struct work_stuff *)); #if 0 static int demangle_method_args PARAMS ((struct work_stuff *, const char **, string *)); #endif static char * internal_cplus_demangle PARAMS ((struct work_stuff *, const char *)); static int demangle_template_template_parm PARAMS ((struct work_stuff *work, const char **, string *)); static int demangle_template PARAMS ((struct work_stuff *work, const char **, string *, string *, int, int)); static int arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **, const char **)); static int demangle_class_name PARAMS ((struct work_stuff *, const char **, string *)); static int demangle_qualified PARAMS ((struct work_stuff *, const char **, string *, int, int)); static int demangle_class PARAMS ((struct work_stuff *, const char **, string *)); static int demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *)); static int demangle_signature PARAMS ((struct work_stuff *, const char **, string *)); static int demangle_prefix PARAMS ((struct work_stuff *, const char **, string *)); static int gnu_special PARAMS ((struct work_stuff *, const char **, string *)); static int arm_special PARAMS ((const char **, string *)); static void string_need PARAMS ((string *, int)); static void string_delete PARAMS ((string *)); static void string_init PARAMS ((string *)); static void string_clear PARAMS ((string *)); #if 0 static int string_empty PARAMS ((string *)); #endif static void string_append PARAMS ((string *, const char *)); static void string_appends PARAMS ((string *, string *)); static void string_appendn PARAMS ((string *, const char *, int)); static void string_prepend PARAMS ((string *, const char *)); static void string_prependn PARAMS ((string *, const char *, int)); static void string_append_template_idx PARAMS ((string *, int)); static int get_count PARAMS ((const char **, int *)); static int consume_count PARAMS ((const char **)); static int consume_count_with_underscores PARAMS ((const char**)); static int demangle_args PARAMS ((struct work_stuff *, const char **, string *)); static int demangle_nested_args PARAMS ((struct work_stuff*, const char**, string*)); static int do_type PARAMS ((struct work_stuff *, const char **, string *)); static int do_arg PARAMS ((struct work_stuff *, const char **, string *)); static void demangle_function_name PARAMS ((struct work_stuff *, const char **, string *, const char *)); static int iterate_demangle_function PARAMS ((struct work_stuff *, const char **, string *, const char *)); static void remember_type PARAMS ((struct work_stuff *, const char *, int)); static void remember_Btype PARAMS ((struct work_stuff *, const char *, int, int)); static int register_Btype PARAMS ((struct work_stuff *)); static void remember_Ktype PARAMS ((struct work_stuff *, const char *, int)); static void forget_types PARAMS ((struct work_stuff *)); static void forget_B_and_K_types PARAMS ((struct work_stuff *)); static void string_prepends PARAMS ((string *, string *)); static int demangle_template_value_parm PARAMS ((struct work_stuff*, const char**, string*, type_kind_t)); static int do_hpacc_template_const_value PARAMS ((struct work_stuff *, const char **, string *)); static int do_hpacc_template_literal PARAMS ((struct work_stuff *, const char **, string *)); static int snarf_numeric_literal PARAMS ((const char **, string *)); /* There is a TYPE_QUAL value for each type qualifier. They can be combined by bitwise-or to form the complete set of qualifiers for a type. */ #define TYPE_UNQUALIFIED 0x0 #define TYPE_QUAL_CONST 0x1 #define TYPE_QUAL_VOLATILE 0x2 #define TYPE_QUAL_RESTRICT 0x4 static int code_for_qualifier PARAMS ((int)); static const char* qualifier_string PARAMS ((int)); static const char* demangle_qualifier PARAMS ((int)); static int demangle_expression PARAMS ((struct work_stuff *, const char **, string *, type_kind_t)); static int demangle_integral_value PARAMS ((struct work_stuff *, const char **, string *)); static int demangle_real_value PARAMS ((struct work_stuff *, const char **, string *)); static void demangle_arm_hp_template PARAMS ((struct work_stuff *, const char **, int, string *)); static void recursively_demangle PARAMS ((struct work_stuff *, const char **, string *, int)); static void grow_vect PARAMS ((char **, size_t *, size_t, int)); /* Translate count to integer, consuming tokens in the process. Conversion terminates on the first non-digit character. Trying to consume something that isn't a count results in no consumption of input and a return of -1. Overflow consumes the rest of the digits, and returns -1. */ static int consume_count (type) const char **type; { int count = 0; if (! g_ascii_isdigit ((unsigned char)**type)) return -1; while (g_ascii_isdigit ((unsigned char)**type)) { count *= 10; /* Check for overflow. We assume that count is represented using two's-complement; no power of two is divisible by ten, so if an overflow occurs when multiplying by ten, the result will not be a multiple of ten. */ if ((count % 10) != 0) { while (g_ascii_isdigit ((unsigned char) **type)) (*type)++; return -1; } count += **type - '0'; (*type)++; } if (count < 0) count = -1; return (count); } /* Like consume_count, but for counts that are preceded and followed by '_' if they are greater than 10. Also, -1 is returned for failure, since 0 can be a valid value. */ static int consume_count_with_underscores (mangled) const char **mangled; { int idx; if (**mangled == '_') { (*mangled)++; if (!g_ascii_isdigit ((unsigned char)**mangled)) return -1; idx = consume_count (mangled); if (**mangled != '_') /* The trailing underscore was missing. */ return -1; (*mangled)++; } else { if (**mangled < '0' || **mangled > '9') return -1; idx = **mangled - '0'; (*mangled)++; } return idx; } /* C is the code for a type-qualifier. Return the TYPE_QUAL corresponding to this qualifier. */ static int code_for_qualifier (c) int c; { switch (c) { case 'C': return TYPE_QUAL_CONST; case 'V': return TYPE_QUAL_VOLATILE; case 'u': return TYPE_QUAL_RESTRICT; default: break; } /* C was an invalid qualifier. */ abort (); } /* Return the string corresponding to the qualifiers given by TYPE_QUALS. */ static const char* qualifier_string (type_quals) int type_quals; { switch (type_quals) { case TYPE_UNQUALIFIED: return ""; case TYPE_QUAL_CONST: return "const"; case TYPE_QUAL_VOLATILE: return "volatile"; case TYPE_QUAL_RESTRICT: return "__restrict"; case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE: return "const volatile"; case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT: return "const __restrict"; case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: return "volatile __restrict"; case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: return "const volatile __restrict"; default: break; } /* TYPE_QUALS was an invalid qualifier set. */ abort (); } /* C is the code for a type-qualifier. Return the string corresponding to this qualifier. This function should only be called with a valid qualifier code. */ static const char* demangle_qualifier (c) int c; { return qualifier_string (code_for_qualifier (c)); } /* Takes operator name as e.g. "++" and returns mangled operator name (e.g. "postincrement_expr"), or NULL if not found. If OPTIONS & DMGL_ANSI == 1, return the ANSI name; if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */ /* Add a routine to set the demangling style to be sure it is valid and allow for any demangler initialization that maybe necessary. */ /* Do string name to style translation */ /* char *cplus_demangle (const char *mangled, int options) If MANGLED is a mangled function name produced by GNU C++, then a pointer to a @code{malloc}ed string giving a C++ representation of the name will be returned; otherwise NULL will be returned. It is the caller's responsibility to free the string which is returned. The OPTIONS arg may contain one or more of the following bits: DMGL_ANSI ANSI qualifiers such as `const' and `void' are included. DMGL_PARAMS Function parameters are included. For example, cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)" cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)" cplus_demangle ("foo__1Ai", 0) => "A::foo" cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)" cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)" cplus_demangle ("foo__1Afe", 0) => "A::foo" Note that any leading underscores, or other such characters prepended by the compilation system, are presumed to have already been stripped from MANGLED. */ char * sysprof_cplus_demangle (mangled, options) const char *mangled; int options; { char *ret; struct work_stuff work[1]; if (current_demangling_style == no_demangling) return g_strdup (mangled); memset ((char *) work, 0, sizeof (work)); work->options = options; if ((work->options & DMGL_STYLE_MASK) == 0) work->options |= (int) current_demangling_style & DMGL_STYLE_MASK; /* The V3 ABI demangling is implemented elsewhere. */ if (GNU_V3_DEMANGLING || AUTO_DEMANGLING) { ret = cplus_demangle_v3 (mangled, work->options); if (ret || GNU_V3_DEMANGLING) return ret; } if (JAVA_DEMANGLING) { ret = java_demangle_v3 (mangled); if (ret) return ret; } if (GNAT_DEMANGLING) return ada_demangle(mangled,options); ret = internal_cplus_demangle (work, mangled); squangle_mop_up (work); return (ret); } /* Assuming *OLD_VECT points to an array of *SIZE objects of size ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects, updating *OLD_VECT and *SIZE as necessary. */ static void grow_vect (old_vect, size, min_size, element_size) char **old_vect; size_t *size; size_t min_size; int element_size; { if (*size < min_size) { *size *= 2; if (*size < min_size) *size = min_size; *old_vect = (void *) g_realloc (*old_vect, *size * element_size); } } /* Demangle ada names: 1. Discard final __{DIGIT}+ or ${DIGIT}+ 2. Convert other instances of embedded "__" to `.'. 3. Discard leading _ada_. 4. Remove everything after first ___ if it is followed by 'X'. 5. Put symbols that should be suppressed in <...> brackets. The resulting string is valid until the next call of ada_demangle. */ static char * ada_demangle (mangled, option) const char *mangled; int option ATTRIBUTE_UNUSED; { int i, j; int len0; const char* p; char *demangled = NULL; int changed; size_t demangled_size = 0; changed = 0; if (strncmp (mangled, "_ada_", 5) == 0) { mangled += 5; changed = 1; } if (mangled[0] == '_' || mangled[0] == '<') goto Suppress; p = strstr (mangled, "___"); if (p == NULL) len0 = strlen (mangled); else { if (p[3] == 'X') { len0 = p - mangled; changed = 1; } else goto Suppress; } /* Make demangled big enough for possible expansion by operator name. */ grow_vect (&demangled, &demangled_size, 2 * len0 + 1, sizeof (char)); if (g_ascii_isdigit ((unsigned char) mangled[len0 - 1])) { for (i = len0 - 2; i >= 0 && g_ascii_isdigit ((unsigned char) mangled[i]); i -= 1) ; if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_') { len0 = i - 1; changed = 1; } else if (mangled[i] == '$') { len0 = i; changed = 1; } } for (i = 0, j = 0; i < len0 && ! g_ascii_isalpha ((unsigned char)mangled[i]); i += 1, j += 1) demangled[j] = mangled[i]; while (i < len0) { if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_') { demangled[j] = '.'; changed = 1; i += 2; j += 1; } else { demangled[j] = mangled[i]; i += 1; j += 1; } } demangled[j] = '\000'; for (i = 0; demangled[i] != '\0'; i += 1) if (g_ascii_isupper ((unsigned char)demangled[i]) || demangled[i] == ' ') goto Suppress; if (! changed) return NULL; else return demangled; Suppress: grow_vect (&demangled, &demangled_size, strlen (mangled) + 3, sizeof (char)); if (mangled[0] == '<') strcpy (demangled, mangled); else sprintf (demangled, "<%s>", mangled); return demangled; } /* This function performs most of what cplus_demangle use to do, but to be able to demangle a name with a B, K or n code, we need to have a longer term memory of what types have been seen. The original now initializes and cleans up the squangle code info, while internal calls go directly to this routine to avoid resetting that info. */ static char * internal_cplus_demangle (work, mangled) struct work_stuff *work; const char *mangled; { string decl; int success = 0; char *demangled = NULL; int s1, s2, s3, s4; s1 = work->constructor; s2 = work->destructor; s3 = work->static_type; s4 = work->type_quals; work->constructor = work->destructor = 0; work->type_quals = TYPE_UNQUALIFIED; work->dllimported = 0; if ((mangled != NULL) && (*mangled != '\0')) { string_init (&decl); /* First check to see if gnu style demangling is active and if the string to be demangled contains a CPLUS_MARKER. If so, attempt to recognize one of the gnu special forms rather than looking for a standard prefix. In particular, don't worry about whether there is a "__" string in the mangled string. Consider "_$_5__foo" for example. */ if ((AUTO_DEMANGLING || GNU_DEMANGLING)) { success = gnu_special (work, &mangled, &decl); } if (!success) { success = demangle_prefix (work, &mangled, &decl); } if (success && (*mangled != '\0')) { success = demangle_signature (work, &mangled, &decl); } if (work->constructor == 2) { string_prepend (&decl, "global constructors keyed to "); work->constructor = 0; } else if (work->destructor == 2) { string_prepend (&decl, "global destructors keyed to "); work->destructor = 0; } else if (work->dllimported == 1) { string_prepend (&decl, "import stub for "); work->dllimported = 0; } demangled = mop_up (work, &decl, success); } work->constructor = s1; work->destructor = s2; work->static_type = s3; work->type_quals = s4; return demangled; } /* Clear out and squangling related storage */ static void squangle_mop_up (work) struct work_stuff *work; { /* clean up the B and K type mangling types. */ forget_B_and_K_types (work); if (work -> btypevec != NULL) { g_free ((char *) work -> btypevec); } if (work -> ktypevec != NULL) { g_free ((char *) work -> ktypevec); } } /* Copy the work state and storage. */ static void work_stuff_copy_to_from (to, from) struct work_stuff *to; struct work_stuff *from; { int i; delete_work_stuff (to); /* Shallow-copy scalars. */ memcpy (to, from, sizeof (*to)); /* Deep-copy dynamic storage. */ if (from->typevec_size) to->typevec = (char **) g_malloc (from->typevec_size * sizeof (to->typevec[0])); for (i = 0; i < from->ntypes; i++) { int len = strlen (from->typevec[i]) + 1; to->typevec[i] = g_malloc (len); memcpy (to->typevec[i], from->typevec[i], len); } if (from->ksize) to->ktypevec = (char **) g_malloc (from->ksize * sizeof (to->ktypevec[0])); for (i = 0; i < from->numk; i++) { int len = strlen (from->ktypevec[i]) + 1; to->ktypevec[i] = g_malloc (len); memcpy (to->ktypevec[i], from->ktypevec[i], len); } if (from->bsize) to->btypevec = (char **) g_malloc (from->bsize * sizeof (to->btypevec[0])); for (i = 0; i < from->numb; i++) { int len = strlen (from->btypevec[i]) + 1; to->btypevec[i] = g_malloc (len); memcpy (to->btypevec[i], from->btypevec[i], len); } if (from->ntmpl_args) to->tmpl_argvec = (char **) g_malloc (from->ntmpl_args * sizeof (to->tmpl_argvec[0])); for (i = 0; i < from->ntmpl_args; i++) { int len = strlen (from->tmpl_argvec[i]) + 1; to->tmpl_argvec[i] = g_malloc (len); memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len); } if (from->previous_argument) { to->previous_argument = (string*) g_malloc (sizeof (string)); string_init (to->previous_argument); string_appends (to->previous_argument, from->previous_argument); } } /* Delete dynamic stuff in work_stuff that is not to be re-used. */ static void delete_non_B_K_work_stuff (work) struct work_stuff *work; { /* Discard the remembered types, if any. */ forget_types (work); if (work -> typevec != NULL) { g_free ((char *) work -> typevec); work -> typevec = NULL; work -> typevec_size = 0; } if (work->tmpl_argvec) { int i; for (i = 0; i < work->ntmpl_args; i++) if (work->tmpl_argvec[i]) g_free ((char*) work->tmpl_argvec[i]); g_free ((char*) work->tmpl_argvec); work->tmpl_argvec = NULL; } if (work->previous_argument) { string_delete (work->previous_argument); g_free ((char*) work->previous_argument); work->previous_argument = NULL; } } /* Delete all dynamic storage in work_stuff. */ static void delete_work_stuff (work) struct work_stuff *work; { delete_non_B_K_work_stuff (work); squangle_mop_up (work); } /* Clear out any mangled storage */ static char * mop_up (work, declp, success) struct work_stuff *work; string *declp; int success; { char *demangled = NULL; delete_non_B_K_work_stuff (work); /* If demangling was successful, ensure that the demangled string is null terminated and return it. Otherwise, free the demangling decl. */ if (!success) { string_delete (declp); } else { string_appendn (declp, "", 1); demangled = declp->b; } return (demangled); } /* LOCAL FUNCTION demangle_signature -- demangle the signature part of a mangled name SYNOPSIS static int demangle_signature (struct work_stuff *work, const char **mangled, string *declp); DESCRIPTION Consume and demangle the signature portion of the mangled name. DECLP is the string where demangled output is being built. At entry it contains the demangled root name from the mangled name prefix. I.E. either a demangled operator name or the root function name. In some special cases, it may contain nothing. *MANGLED points to the current unconsumed location in the mangled name. As tokens are consumed and demangling is performed, the pointer is updated to continuously point at the next token to be consumed. Demangling GNU style mangled names is nasty because there is no explicit token that marks the start of the outermost function argument list. */ static int demangle_signature (work, mangled, declp) struct work_stuff *work; const char **mangled; string *declp; { int success = 1; int func_done = 0; int expect_func = 0; int expect_return_type = 0; const char *oldmangled = NULL; string trawname; string tname; while (success && (**mangled != '\0')) { switch (**mangled) { case 'Q': oldmangled = *mangled; success = demangle_qualified (work, mangled, declp, 1, 0); if (success) remember_type (work, oldmangled, *mangled - oldmangled); if (AUTO_DEMANGLING || GNU_DEMANGLING) expect_func = 1; oldmangled = NULL; break; case 'K': oldmangled = *mangled; success = demangle_qualified (work, mangled, declp, 1, 0); if (AUTO_DEMANGLING || GNU_DEMANGLING) { expect_func = 1; } oldmangled = NULL; break; case 'S': /* Static member function */ if (oldmangled == NULL) { oldmangled = *mangled; } (*mangled)++; work -> static_type = 1; break; case 'C': case 'V': case 'u': work->type_quals |= code_for_qualifier (**mangled); /* a qualified member function */ if (oldmangled == NULL) oldmangled = *mangled; (*mangled)++; break; case 'L': /* Local class name follows after "Lnnn_" */ if (HP_DEMANGLING) { while (**mangled && (**mangled != '_')) (*mangled)++; if (!**mangled) success = 0; else (*mangled)++; } else success = 0; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (oldmangled == NULL) { oldmangled = *mangled; } work->temp_start = -1; /* uppermost call to demangle_class */ success = demangle_class (work, mangled, declp); if (success) { remember_type (work, oldmangled, *mangled - oldmangled); } if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING) { /* EDG and others will have the "F", so we let the loop cycle if we are looking at one. */ if (**mangled != 'F') expect_func = 1; } oldmangled = NULL; break; case 'B': { string s; success = do_type (work, mangled, &s); if (success) { string_append (&s, SCOPE_STRING (work)); string_prepends (declp, &s); string_delete (&s); } oldmangled = NULL; expect_func = 1; } break; case 'F': /* Function */ /* ARM/HP style demangling includes a specific 'F' character after the class name. For GNU style, it is just implied. So we can safely just consume any 'F' at this point and be compatible with either style. */ oldmangled = NULL; func_done = 1; (*mangled)++; /* For lucid/ARM/HP style we have to forget any types we might have remembered up to this point, since they were not argument types. GNU style considers all types seen as available for back references. See comment in demangle_args() */ if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) { forget_types (work); } success = demangle_args (work, mangled, declp); /* After picking off the function args, we expect to either find the function return type (preceded by an '_') or the end of the string. */ if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_') { ++(*mangled); /* At this level, we do not care about the return type. */ success = do_type (work, mangled, &tname); string_delete (&tname); } break; case 't': /* G++ Template */ string_init(&trawname); string_init(&tname); if (oldmangled == NULL) { oldmangled = *mangled; } success = demangle_template (work, mangled, &tname, &trawname, 1, 1); if (success) { remember_type (work, oldmangled, *mangled - oldmangled); } string_append (&tname, SCOPE_STRING (work)); string_prepends(declp, &tname); if (work -> destructor & 1) { string_prepend (&trawname, "~"); string_appends (declp, &trawname); work->destructor -= 1; } if ((work->constructor & 1) || (work->destructor & 1)) { string_appends (declp, &trawname); work->constructor -= 1; } string_delete(&trawname); string_delete(&tname); oldmangled = NULL; expect_func = 1; break; case '_': if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type) { /* Read the return type. */ string return_type; (*mangled)++; success = do_type (work, mangled, &return_type); APPEND_BLANK (&return_type); string_prepends (declp, &return_type); string_delete (&return_type); break; } else /* At the outermost level, we cannot have a return type specified, so if we run into another '_' at this point we are dealing with a mangled name that is either bogus, or has been mangled by some algorithm we don't know how to deal with. So just reject the entire demangling. */ /* However, "_nnn" is an expected suffix for alternate entry point numbered nnn for a function, with HP aCC, so skip over that without reporting failure. pai/1997-09-04 */ if (HP_DEMANGLING) { (*mangled)++; while (**mangled && g_ascii_isdigit ((unsigned char)**mangled)) (*mangled)++; } else success = 0; break; case 'H': if (AUTO_DEMANGLING || GNU_DEMANGLING) { /* A G++ template function. Read the template arguments. */ success = demangle_template (work, mangled, declp, 0, 0, 0); if (!(work->constructor & 1)) expect_return_type = 1; (*mangled)++; break; } else /* fall through */ {;} default: if (AUTO_DEMANGLING || GNU_DEMANGLING) { /* Assume we have stumbled onto the first outermost function argument token, and start processing args. */ func_done = 1; success = demangle_args (work, mangled, declp); } else { /* Non-GNU demanglers use a specific token to mark the start of the outermost function argument tokens. Typically 'F', for ARM/HP-demangling, for example. So if we find something we are not prepared for, it must be an error. */ success = 0; } break; } /* if (AUTO_DEMANGLING || GNU_DEMANGLING) */ { if (success && expect_func) { func_done = 1; if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) { forget_types (work); } success = demangle_args (work, mangled, declp); /* Since template include the mangling of their return types, we must set expect_func to 0 so that we don't try do demangle more arguments the next time we get here. */ expect_func = 0; } } } if (success && !func_done) { if (AUTO_DEMANGLING || GNU_DEMANGLING) { /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and bar__3fooi is 'foo::bar(int)'. We get here when we find the first case, and need to ensure that the '(void)' gets added to the current declp. Note that with ARM/HP, the first case represents the name of a static data member 'foo::bar', which is in the current declp, so we leave it alone. */ success = demangle_args (work, mangled, declp); } } if (success && PRINT_ARG_TYPES) { if (work->static_type) string_append (declp, " static"); if (work->type_quals != TYPE_UNQUALIFIED) { APPEND_BLANK (declp); string_append (declp, qualifier_string (work->type_quals)); } } return (success); } #if 0 static int demangle_method_args (work, mangled, declp) struct work_stuff *work; const char **mangled; string *declp; { int success = 0; if (work -> static_type) { string_append (declp, *mangled + 1); *mangled += strlen (*mangled); success = 1; } else { success = demangle_args (work, mangled, declp); } return (success); } #endif static int demangle_template_template_parm (work, mangled, tname) struct work_stuff *work; const char **mangled; string *tname; { int i; int r; int need_comma = 0; int success = 1; string temp; string_append (tname, "template <"); /* get size of template parameter list */ if (get_count (mangled, &r)) { for (i = 0; i < r; i++) { if (need_comma) { string_append (tname, ", "); } /* Z for type parameters */ if (**mangled == 'Z') { (*mangled)++; string_append (tname, "class"); } /* z for template parameters */ else if (**mangled == 'z') { (*mangled)++; success = demangle_template_template_parm (work, mangled, tname); if (!success) { break; } } else { /* temp is initialized in do_type */ success = do_type (work, mangled, &temp); if (success) { string_appends (tname, &temp); } string_delete(&temp); if (!success) { break; } } need_comma = 1; } } if (tname->p[-1] == '>') string_append (tname, " "); string_append (tname, "> class"); return (success); } static int demangle_expression (work, mangled, s, tk) struct work_stuff *work; const char** mangled; string* s; type_kind_t tk; { int need_operator = 0; int success; success = 1; string_appendn (s, "(", 1); (*mangled)++; while (success && **mangled != 'W' && **mangled != '\0') { if (need_operator) { size_t i; size_t len; success = 0; len = strlen (*mangled); for (i = 0; i < G_N_ELEMENTS (optable); ++i) { size_t l = strlen (optable[i].in); if (l <= len && memcmp (optable[i].in, *mangled, l) == 0) { string_appendn (s, " ", 1); string_append (s, optable[i].out); string_appendn (s, " ", 1); success = 1; (*mangled) += l; break; } } if (!success) break; } else need_operator = 1; success = demangle_template_value_parm (work, mangled, s, tk); } if (**mangled != 'W') success = 0; else { string_appendn (s, ")", 1); (*mangled)++; } return success; } static int demangle_integral_value (work, mangled, s) struct work_stuff *work; const char** mangled; string* s; { int success; if (**mangled == 'E') success = demangle_expression (work, mangled, s, tk_integral); else if (**mangled == 'Q' || **mangled == 'K') success = demangle_qualified (work, mangled, s, 0, 1); else { int value; /* By default, we let the number decide whether we shall consume an underscore. */ int multidigit_without_leading_underscore = 0; int leave_following_underscore = 0; success = 0; if (**mangled == '_') { if (mangled[0][1] == 'm') { /* Since consume_count_with_underscores does not handle the `m'-prefix we must do it here, using consume_count and adjusting underscores: we have to consume the underscore matching the prepended one. */ multidigit_without_leading_underscore = 1; string_appendn (s, "-", 1); (*mangled) += 2; } else { /* Do not consume a following underscore; consume_count_with_underscores will consume what should be consumed. */ leave_following_underscore = 1; } } else { /* Negative numbers are indicated with a leading `m'. */ if (**mangled == 'm') { string_appendn (s, "-", 1); (*mangled)++; } /* Since consume_count_with_underscores does not handle multi-digit numbers that do not start with an underscore, and this number can be an integer template parameter, we have to call consume_count. */ multidigit_without_leading_underscore = 1; /* These multi-digit numbers never end on an underscore, so if there is one then don't eat it. */ leave_following_underscore = 1; } /* We must call consume_count if we expect to remove a trailing underscore, since consume_count_with_underscores expects the leading underscore (that we consumed) if it is to handle multi-digit numbers. */ if (multidigit_without_leading_underscore) value = consume_count (mangled); else value = consume_count_with_underscores (mangled); if (value != -1) { char buf[INTBUF_SIZE]; sprintf (buf, "%d", value); string_append (s, buf); /* Numbers not otherwise delimited, might have an underscore appended as a delimeter, which we should skip. ??? This used to always remove a following underscore, which is wrong. If other (arbitrary) cases are followed by an underscore, we need to do something more radical. */ if ((value > 9 || multidigit_without_leading_underscore) && ! leave_following_underscore && **mangled == '_') (*mangled)++; /* All is well. */ success = 1; } } return success; } /* Demangle the real value in MANGLED. */ static int demangle_real_value (work, mangled, s) struct work_stuff *work; const char **mangled; string* s; { if (**mangled == 'E') return demangle_expression (work, mangled, s, tk_real); if (**mangled == 'm') { string_appendn (s, "-", 1); (*mangled)++; } while (g_ascii_isdigit ((unsigned char)**mangled)) { string_appendn (s, *mangled, 1); (*mangled)++; } if (**mangled == '.') /* fraction */ { string_appendn (s, ".", 1); (*mangled)++; while (g_ascii_isdigit ((unsigned char)**mangled)) { string_appendn (s, *mangled, 1); (*mangled)++; } } if (**mangled == 'e') /* exponent */ { string_appendn (s, "e", 1); (*mangled)++; while (g_ascii_isdigit ((unsigned char)**mangled)) { string_appendn (s, *mangled, 1); (*mangled)++; } } return 1; } static int demangle_template_value_parm (work, mangled, s, tk) struct work_stuff *work; const char **mangled; string* s; type_kind_t tk; { int success = 1; if (**mangled == 'Y') { /* The next argument is a template parameter. */ int idx; (*mangled)++; idx = consume_count_with_underscores (mangled); if (idx == -1 || (work->tmpl_argvec && idx >= work->ntmpl_args) || consume_count_with_underscores (mangled) == -1) return -1; if (work->tmpl_argvec) string_append (s, work->tmpl_argvec[idx]); else string_append_template_idx (s, idx); } else if (tk == tk_integral) success = demangle_integral_value (work, mangled, s); else if (tk == tk_char) { char tmp[2]; int val; if (**mangled == 'm') { string_appendn (s, "-", 1); (*mangled)++; } string_appendn (s, "'", 1); val = consume_count(mangled); if (val <= 0) success = 0; else { tmp[0] = (char)val; tmp[1] = '\0'; string_appendn (s, &tmp[0], 1); string_appendn (s, "'", 1); } } else if (tk == tk_bool) { int val = consume_count (mangled); if (val == 0) string_appendn (s, "false", 5); else if (val == 1) string_appendn (s, "true", 4); else success = 0; } else if (tk == tk_real) success = demangle_real_value (work, mangled, s); else if (tk == tk_pointer || tk == tk_reference) { if (**mangled == 'Q') success = demangle_qualified (work, mangled, s, /*isfuncname=*/0, /*append=*/1); else { int symbol_len = consume_count (mangled); if (symbol_len == -1) return -1; if (symbol_len == 0) string_appendn (s, "0", 1); else { char *p = g_malloc (symbol_len + 1), *q; strncpy (p, *mangled, symbol_len); p [symbol_len] = '\0'; /* We use cplus_demangle here, rather than internal_cplus_demangle, because the name of the entity mangled here does not make use of any of the squangling or type-code information we have built up thus far; it is mangled independently. */ q = sysprof_cplus_demangle (p, work->options); if (tk == tk_pointer) string_appendn (s, "&", 1); /* FIXME: Pointer-to-member constants should get a qualifying class name here. */ if (q) { string_append (s, q); g_free (q); } else string_append (s, p); g_free (p); } *mangled += symbol_len; } } return success; } /* Demangle the template name in MANGLED. The full name of the template (e.g., S) is placed in TNAME. The name without the template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is non-NULL. If IS_TYPE is nonzero, this template is a type template, not a function template. If both IS_TYPE and REMEMBER are nonzero, the template is remembered in the list of back-referenceable types. */ static int demangle_template (work, mangled, tname, trawname, is_type, remember) struct work_stuff *work; const char **mangled; string *tname; string *trawname; int is_type; int remember; { int i; int r; int need_comma = 0; int success = 0; int is_java_array = 0; string temp; (*mangled)++; if (is_type) { /* get template name */ if (**mangled == 'z') { int idx; (*mangled)++; (*mangled)++; idx = consume_count_with_underscores (mangled); if (idx == -1 || (work->tmpl_argvec && idx >= work->ntmpl_args) || consume_count_with_underscores (mangled) == -1) return (0); if (work->tmpl_argvec) { string_append (tname, work->tmpl_argvec[idx]); if (trawname) string_append (trawname, work->tmpl_argvec[idx]); } else { string_append_template_idx (tname, idx); if (trawname) string_append_template_idx (trawname, idx); } } else { if ((r = consume_count (mangled)) <= 0 || (int) strlen (*mangled) < r) { return (0); } is_java_array = (work -> options & DMGL_JAVA) && strncmp (*mangled, "JArray1Z", 8) == 0; if (! is_java_array) { string_appendn (tname, *mangled, r); } if (trawname) string_appendn (trawname, *mangled, r); *mangled += r; } } if (!is_java_array) string_append (tname, "<"); /* get size of template parameter list */ if (!get_count (mangled, &r)) { return (0); } if (!is_type) { /* Create an array for saving the template argument values. */ work->tmpl_argvec = (char**) g_malloc (r * sizeof (char *)); work->ntmpl_args = r; for (i = 0; i < r; i++) work->tmpl_argvec[i] = 0; } for (i = 0; i < r; i++) { if (need_comma) { string_append (tname, ", "); } /* Z for type parameters */ if (**mangled == 'Z') { (*mangled)++; /* temp is initialized in do_type */ success = do_type (work, mangled, &temp); if (success) { string_appends (tname, &temp); if (!is_type) { /* Save the template argument. */ int len = temp.p - temp.b; work->tmpl_argvec[i] = g_malloc (len + 1); memcpy (work->tmpl_argvec[i], temp.b, len); work->tmpl_argvec[i][len] = '\0'; } } string_delete(&temp); if (!success) { break; } } /* z for template parameters */ else if (**mangled == 'z') { int r2; (*mangled)++; success = demangle_template_template_parm (work, mangled, tname); if (success && (r2 = consume_count (mangled)) > 0 && (int) strlen (*mangled) >= r2) { string_append (tname, " "); string_appendn (tname, *mangled, r2); if (!is_type) { /* Save the template argument. */ int len = r2; work->tmpl_argvec[i] = g_malloc (len + 1); memcpy (work->tmpl_argvec[i], *mangled, len); work->tmpl_argvec[i][len] = '\0'; } *mangled += r2; } if (!success) { break; } } else { string param; string* s; /* otherwise, value parameter */ /* temp is initialized in do_type */ success = do_type (work, mangled, &temp); string_delete(&temp); if (!success) break; if (!is_type) { s = ¶m; string_init (s); } else s = tname; success = demangle_template_value_parm (work, mangled, s, (type_kind_t) success); if (!success) { if (!is_type) string_delete (s); success = 0; break; } if (!is_type) { int len = s->p - s->b; work->tmpl_argvec[i] = g_malloc (len + 1); memcpy (work->tmpl_argvec[i], s->b, len); work->tmpl_argvec[i][len] = '\0'; string_appends (tname, s); string_delete (s); } } need_comma = 1; } if (is_java_array) { string_append (tname, "[]"); } else { if (tname->p[-1] == '>') string_append (tname, " "); string_append (tname, ">"); } if (is_type && remember) { const int bindex = register_Btype (work); remember_Btype (work, tname->b, LEN_STRING (tname), bindex); } /* if (work -> static_type) { string_append (declp, *mangled + 1); *mangled += strlen (*mangled); success = 1; } else { success = demangle_args (work, mangled, declp); } } */ return (success); } static int arm_pt (work, mangled, n, anchor, args) struct work_stuff *work; const char *mangled; int n; const char **anchor, **args; { /* Check if ARM template with "__pt__" in it ("parameterized type") */ /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */ if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__"))) { int len; *args = *anchor + 6; len = consume_count (args); if (len == -1) return 0; if (*args + len == mangled + n && **args == '_') { ++*args; return 1; } } if (AUTO_DEMANGLING || EDG_DEMANGLING) { if ((*anchor = strstr (mangled, "__tm__")) || (*anchor = strstr (mangled, "__ps__")) || (*anchor = strstr (mangled, "__pt__"))) { int len; *args = *anchor + 6; len = consume_count (args); if (len == -1) return 0; if (*args + len == mangled + n && **args == '_') { ++*args; return 1; } } else if ((*anchor = strstr (mangled, "__S"))) { int len; *args = *anchor + 3; len = consume_count (args); if (len == -1) return 0; if (*args + len == mangled + n && **args == '_') { ++*args; return 1; } } } return 0; } static void demangle_arm_hp_template (work, mangled, n, declp) struct work_stuff *work; const char **mangled; int n; string *declp; { const char *p; const char *args; const char *e = *mangled + n; string arg; /* Check for HP aCC template spec: classXt1t2 where t1, t2 are template args */ if (HP_DEMANGLING && ((*mangled)[n] == 'X')) { char *start_spec_args = NULL; int hold_options; /* First check for and omit template specialization pseudo-arguments, such as in "Spec<#1,#1.*>" */ start_spec_args = strchr (*mangled, '<'); if (start_spec_args && (start_spec_args - *mangled < n)) string_appendn (declp, *mangled, start_spec_args - *mangled); else string_appendn (declp, *mangled, n); (*mangled) += n + 1; string_init (&arg); if (work->temp_start == -1) /* non-recursive call */ work->temp_start = declp->p - declp->b; /* We want to unconditionally demangle parameter types in template parameters. */ hold_options = work->options; work->options |= DMGL_PARAMS; string_append (declp, "<"); while (1) { string_delete (&arg); switch (**mangled) { case 'T': /* 'T' signals a type parameter */ (*mangled)++; if (!do_type (work, mangled, &arg)) goto hpacc_template_args_done; break; case 'U': case 'S': /* 'U' or 'S' signals an integral value */ if (!do_hpacc_template_const_value (work, mangled, &arg)) goto hpacc_template_args_done; break; case 'A': /* 'A' signals a named constant expression (literal) */ if (!do_hpacc_template_literal (work, mangled, &arg)) goto hpacc_template_args_done; break; default: /* Today, 1997-09-03, we have only the above types of template parameters */ /* FIXME: maybe this should fail and return null */ goto hpacc_template_args_done; } string_appends (declp, &arg); /* Check if we're at the end of template args. 0 if at end of static member of template class, _ if done with template args for a function */ if ((**mangled == '\000') || (**mangled == '_')) break; else string_append (declp, ","); } hpacc_template_args_done: string_append (declp, ">"); string_delete (&arg); if (**mangled == '_') (*mangled)++; work->options = hold_options; return; } /* ARM template? (Also handles HP cfront extensions) */ else if (arm_pt (work, *mangled, n, &p, &args)) { int hold_options; string type_str; string_init (&arg); string_appendn (declp, *mangled, p - *mangled); if (work->temp_start == -1) /* non-recursive call */ work->temp_start = declp->p - declp->b; /* We want to unconditionally demangle parameter types in template parameters. */ hold_options = work->options; work->options |= DMGL_PARAMS; string_append (declp, "<"); /* should do error checking here */ while (args < e) { string_delete (&arg); /* Check for type or literal here */ switch (*args) { /* HP cfront extensions to ARM for template args */ /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */ /* FIXME: We handle only numeric literals for HP cfront */ case 'X': /* A typed constant value follows */ args++; if (!do_type (work, &args, &type_str)) goto cfront_template_args_done; string_append (&arg, "("); string_appends (&arg, &type_str); string_delete (&type_str); string_append (&arg, ")"); if (*args != 'L') goto cfront_template_args_done; args++; /* Now snarf a literal value following 'L' */ if (!snarf_numeric_literal (&args, &arg)) goto cfront_template_args_done; break; case 'L': /* Snarf a literal following 'L' */ args++; if (!snarf_numeric_literal (&args, &arg)) goto cfront_template_args_done; break; default: /* Not handling other HP cfront stuff */ { const char* old_args = args; if (!do_type (work, &args, &arg)) goto cfront_template_args_done; /* Fail if we didn't make any progress: prevent infinite loop. */ if (args == old_args) { work->options = hold_options; return; } } } string_appends (declp, &arg); string_append (declp, ","); } cfront_template_args_done: string_delete (&arg); if (args >= e) --declp->p; /* remove extra comma */ string_append (declp, ">"); work->options = hold_options; } else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 && (*mangled)[9] == 'N' && (*mangled)[8] == (*mangled)[10] && strchr (cplus_markers, (*mangled)[8])) { /* A member of the anonymous namespace. */ string_append (declp, "{anonymous}"); } else { if (work->temp_start == -1) /* non-recursive call only */ work->temp_start = 0; /* disable in recursive calls */ string_appendn (declp, *mangled, n); } *mangled += n; } /* Extract a class name, possibly a template with arguments, from the mangled string; qualifiers, local class indicators, etc. have already been dealt with */ static int demangle_class_name (work, mangled, declp) struct work_stuff *work; const char **mangled; string *declp; { int n; int success = 0; n = consume_count (mangled); if (n == -1) return 0; if ((int) strlen (*mangled) >= n) { demangle_arm_hp_template (work, mangled, n, declp); success = 1; } return (success); } /* LOCAL FUNCTION demangle_class -- demangle a mangled class sequence SYNOPSIS static int demangle_class (struct work_stuff *work, const char **mangled, strint *declp) DESCRIPTION DECLP points to the buffer into which demangling is being done. *MANGLED points to the current token to be demangled. On input, it points to a mangled class (I.E. "3foo", "13verylongclass", etc.) On exit, it points to the next token after the mangled class on success, or the first unconsumed token on failure. If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then we are demangling a constructor or destructor. In this case we prepend "class::class" or "class::~class" to DECLP. Otherwise, we prepend "class::" to the current DECLP. Reset the constructor/destructor flags once they have been "consumed". This allows demangle_class to be called later during the same demangling, to do normal class demangling. Returns 1 if demangling is successful, 0 otherwise. */ static int demangle_class (work, mangled, declp) struct work_stuff *work; const char **mangled; string *declp; { int success = 0; int btype; string class_name; char *save_class_name_end = 0; string_init (&class_name); btype = register_Btype (work); if (demangle_class_name (work, mangled, &class_name)) { save_class_name_end = class_name.p; if ((work->constructor & 1) || (work->destructor & 1)) { /* adjust so we don't include template args */ if (work->temp_start && (work->temp_start != -1)) { class_name.p = class_name.b + work->temp_start; } string_prepends (declp, &class_name); if (work -> destructor & 1) { string_prepend (declp, "~"); work -> destructor -= 1; } else { work -> constructor -= 1; } } class_name.p = save_class_name_end; remember_Ktype (work, class_name.b, LEN_STRING(&class_name)); remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype); string_prepend (declp, SCOPE_STRING (work)); string_prepends (declp, &class_name); success = 1; } string_delete (&class_name); return (success); } /* Called when there's a "__" in the mangled name, with `scan' pointing to the rightmost guess. Find the correct "__"-sequence where the function name ends and the signature starts, which is ambiguous with GNU mangling. Call demangle_signature here, so we can make sure we found the right one; *mangled will be consumed so caller will not make further calls to demangle_signature. */ static int iterate_demangle_function (work, mangled, declp, scan) struct work_stuff *work; const char **mangled; string *declp; const char *scan; { const char *mangle_init = *mangled; int success = 0; string decl_init; struct work_stuff work_init; if (*(scan + 2) == '\0') return 0; /* Do not iterate for some demangling modes, or if there's only one "__"-sequence. This is the normal case. */ if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING || strstr (scan + 2, "__") == NULL) { demangle_function_name (work, mangled, declp, scan); return 1; } /* Save state so we can restart if the guess at the correct "__" was wrong. */ string_init (&decl_init); string_appends (&decl_init, declp); memset (&work_init, 0, sizeof work_init); work_stuff_copy_to_from (&work_init, work); /* Iterate over occurrences of __, allowing names and types to have a "__" sequence in them. We must start with the first (not the last) occurrence, since "__" most often occur between independent mangled parts, hence starting at the last occurence inside a signature might get us a "successful" demangling of the signature. */ while (scan[2]) { demangle_function_name (work, mangled, declp, scan); success = demangle_signature (work, mangled, declp); if (success) break; /* Reset demangle state for the next round. */ *mangled = mangle_init; string_clear (declp); string_appends (declp, &decl_init); work_stuff_copy_to_from (work, &work_init); /* Leave this underscore-sequence. */ scan += 2; /* Scan for the next "__" sequence. */ while (*scan && (scan[0] != '_' || scan[1] != '_')) scan++; /* Move to last "__" in this sequence. */ while (*scan && *scan == '_') scan++; scan -= 2; } /* Delete saved state. */ delete_work_stuff (&work_init); string_delete (&decl_init); return success; } /* LOCAL FUNCTION demangle_prefix -- consume the mangled name prefix and find signature SYNOPSIS static int demangle_prefix (struct work_stuff *work, const char **mangled, string *declp); DESCRIPTION Consume and demangle the prefix of the mangled name. While processing the function name root, arrange to call demangle_signature if the root is ambiguous. DECLP points to the string buffer into which demangled output is placed. On entry, the buffer is empty. On exit it contains the root function name, the demangled operator name, or in some special cases either nothing or the completely demangled result. MANGLED points to the current pointer into the mangled name. As each token of the mangled name is consumed, it is updated. Upon entry the current mangled name pointer points to the first character of the mangled name. Upon exit, it should point to the first character of the signature if demangling was successful, or to the first unconsumed character if demangling of the prefix was unsuccessful. Returns 1 on success, 0 otherwise. */ static int demangle_prefix (work, mangled, declp) struct work_stuff *work; const char **mangled; string *declp; { int success = 1; const char *scan; int i; if (strlen(*mangled) > 6 && (strncmp(*mangled, "_imp__", 6) == 0 || strncmp(*mangled, "__imp_", 6) == 0)) { /* it's a symbol imported from a PE dynamic library. Check for both new style prefix _imp__ and legacy __imp_ used by older versions of dlltool. */ (*mangled) += 6; work->dllimported = 1; } else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0) { char *marker = strchr (cplus_markers, (*mangled)[8]); if (marker != NULL && *marker == (*mangled)[10]) { if ((*mangled)[9] == 'D') { /* it's a GNU global destructor to be executed at program exit */ (*mangled) += 11; work->destructor = 2; if (gnu_special (work, mangled, declp)) return success; } else if ((*mangled)[9] == 'I') { /* it's a GNU global constructor to be executed at program init */ (*mangled) += 11; work->constructor = 2; if (gnu_special (work, mangled, declp)) return success; } } } else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0) { /* it's a ARM global destructor to be executed at program exit */ (*mangled) += 7; work->destructor = 2; } else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0) { /* it's a ARM global constructor to be executed at program initial */ (*mangled) += 7; work->constructor = 2; } /* This block of code is a reduction in strength time optimization of: scan = strstr (*mangled, "__"); */ { scan = *mangled; do { scan = strchr (scan, '_'); } while (scan != NULL && *++scan != '_'); if (scan != NULL) --scan; } if (scan != NULL) { /* We found a sequence of two or more '_', ensure that we start at the last pair in the sequence. */ i = strspn (scan, "_"); if (i > 2) { scan += (i - 2); } } if (scan == NULL) { success = 0; } else if (work -> static_type) { if (!g_ascii_isdigit ((unsigned char)scan[0]) && (scan[0] != 't')) { success = 0; } } else if ((scan == *mangled) && (g_ascii_isdigit ((unsigned char)scan[2]) || (scan[2] == 'Q') || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H'))) { /* The ARM says nothing about the mangling of local variables. But cfront mangles local variables by prepending __ to them. As an extension to ARM demangling we handle this case. */ if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING) && g_ascii_isdigit ((unsigned char)scan[2])) { *mangled = scan + 2; consume_count (mangled); string_append (declp, *mangled); *mangled += strlen (*mangled); success = 1; } else { /* A GNU style constructor starts with __[0-9Qt]. But cfront uses names like __Q2_3foo3bar for nested type names. So don't accept this style of constructor for cfront demangling. A GNU style member-template constructor starts with 'H'. */ if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)) work -> constructor += 1; *mangled = scan + 2; } } else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't') { /* Cfront-style parameterized type. Handled later as a signature. */ success = 1; /* ARM template? */ demangle_arm_hp_template (work, mangled, strlen (*mangled), declp); } else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm') || (scan[2] == 'p' && scan[3] == 's') || (scan[2] == 'p' && scan[3] == 't'))) { /* EDG-style parameterized type. Handled later as a signature. */ success = 1; /* EDG template? */ demangle_arm_hp_template (work, mangled, strlen (*mangled), declp); } else if ((scan == *mangled) && !g_ascii_isdigit ((unsigned char)scan[2]) && (scan[2] != 't')) { /* Mangled name starts with "__". Skip over any leading '_' characters, then find the next "__" that separates the prefix from the signature. */ if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) || (arm_special (mangled, declp) == 0)) { while (*scan == '_') { scan++; } if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) { /* No separator (I.E. "__not_mangled"), or empty signature (I.E. "__not_mangled_either__") */ success = 0; } else return iterate_demangle_function (work, mangled, declp, scan); } } else if (*(scan + 2) != '\0') { /* Mangled name does not start with "__" but does have one somewhere in there with non empty stuff after it. Looks like a global function name. Iterate over all "__":s until the right one is found. */ return iterate_demangle_function (work, mangled, declp, scan); } else { /* Doesn't look like a mangled name */ success = 0; } if (!success && (work->constructor == 2 || work->destructor == 2)) { string_append (declp, *mangled); *mangled += strlen (*mangled); success = 1; } return (success); } /* LOCAL FUNCTION gnu_special -- special handling of gnu mangled strings SYNOPSIS static int gnu_special (struct work_stuff *work, const char **mangled, string *declp); DESCRIPTION Process some special GNU style mangling forms that don't fit the normal pattern. For example: _$_3foo (destructor for class foo) _vt$foo (foo virtual table) _vt$foo$bar (foo::bar virtual table) __vt_foo (foo virtual table, new style with thunks) _3foo$varname (static data member) _Q22rs2tu$vw (static data member) __t6vector1Zii (constructor with template) __thunk_4__$_7ostream (virtual function thunk) */ static int gnu_special (work, mangled, declp) struct work_stuff *work; const char **mangled; string *declp; { int n; int success = 1; const char *p; if ((*mangled)[0] == '_' && strchr (cplus_markers, (*mangled)[1]) != NULL && (*mangled)[2] == '_') { /* Found a GNU style destructor, get past "__" */ (*mangled) += 3; work -> destructor += 1; } else if ((*mangled)[0] == '_' && (((*mangled)[1] == '_' && (*mangled)[2] == 'v' && (*mangled)[3] == 't' && (*mangled)[4] == '_') || ((*mangled)[1] == 'v' && (*mangled)[2] == 't' && strchr (cplus_markers, (*mangled)[3]) != NULL))) { /* Found a GNU style virtual table, get past "_vt" and create the decl. Note that we consume the entire mangled input string, which means that demangle_signature has no work to do. */ if ((*mangled)[2] == 'v') (*mangled) += 5; /* New style, with thunks: "__vt_" */ else (*mangled) += 4; /* Old style, no thunks: "_vt" */ while (**mangled != '\0') { switch (**mangled) { case 'Q': case 'K': success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': success = demangle_template (work, mangled, declp, 0, 1, 1); break; default: if (g_ascii_isdigit((unsigned char)*mangled[0])) { n = consume_count(mangled); /* We may be seeing a too-large size, or else a "." indicating a static local symbol. In any case, declare victory and move on; *don't* try to use n to allocate. */ if (n > (int) strlen (*mangled)) { success = 1; break; } } else { n = strcspn (*mangled, cplus_markers); } string_appendn (declp, *mangled, n); (*mangled) += n; } p = strpbrk (*mangled, cplus_markers); if (success && ((p == NULL) || (p == *mangled))) { if (p != NULL) { string_append (declp, SCOPE_STRING (work)); (*mangled)++; } } else { success = 0; break; } } if (success) string_append (declp, " virtual table"); } else if ((*mangled)[0] == '_' && (strchr("0123456789Qt", (*mangled)[1]) != NULL) && (p = strpbrk (*mangled, cplus_markers)) != NULL) { /* static data member, "_3foo$varname" for example */ (*mangled)++; switch (**mangled) { case 'Q': case 'K': success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': success = demangle_template (work, mangled, declp, 0, 1, 1); break; default: n = consume_count (mangled); if (n < 0 || n > (long) strlen (*mangled)) { success = 0; break; } if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 && (*mangled)[9] == 'N' && (*mangled)[8] == (*mangled)[10] && strchr (cplus_markers, (*mangled)[8])) { /* A member of the anonymous namespace. There's information about what identifier or filename it was keyed to, but it's just there to make the mangled name unique; we just step over it. */ string_append (declp, "{anonymous}"); (*mangled) += n; /* Now p points to the marker before the N, so we need to update it to the first marker after what we consumed. */ p = strpbrk (*mangled, cplus_markers); break; } string_appendn (declp, *mangled, n); (*mangled) += n; } if (success && (p == *mangled)) { /* Consumed everything up to the cplus_marker, append the variable name. */ (*mangled)++; string_append (declp, SCOPE_STRING (work)); n = strlen (*mangled); string_appendn (declp, *mangled, n); (*mangled) += n; } else { success = 0; } } else if (strncmp (*mangled, "__thunk_", 8) == 0) { int delta; (*mangled) += 8; delta = consume_count (mangled); if (delta == -1) success = 0; else { char *method = internal_cplus_demangle (work, ++*mangled); if (method) { char buf[50]; sprintf (buf, "virtual function thunk (delta:%d) for ", -delta); string_append (declp, buf); string_append (declp, method); g_free (method); n = strlen (*mangled); (*mangled) += n; } else { success = 0; } } } else if (strncmp (*mangled, "__t", 3) == 0 && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f')) { p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function"; (*mangled) += 4; switch (**mangled) { case 'Q': case 'K': success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': success = demangle_template (work, mangled, declp, 0, 1, 1); break; default: success = do_type (work, mangled, declp); break; } if (success && **mangled != '\0') success = 0; if (success) string_append (declp, p); } else { success = 0; } return (success); } static void recursively_demangle(work, mangled, result, namelength) struct work_stuff *work; const char **mangled; string *result; int namelength; { char * recurse = (char *)NULL; char * recurse_dem = (char *)NULL; recurse = (char *) g_malloc (namelength + 1); memcpy (recurse, *mangled, namelength); recurse[namelength] = '\000'; recurse_dem = sysprof_cplus_demangle (recurse, work->options); if (recurse_dem) { string_append (result, recurse_dem); g_free (recurse_dem); } else { string_appendn (result, *mangled, namelength); } g_free (recurse); *mangled += namelength; } /* LOCAL FUNCTION arm_special -- special handling of ARM/lucid mangled strings SYNOPSIS static int arm_special (const char **mangled, string *declp); DESCRIPTION Process some special ARM style mangling forms that don't fit the normal pattern. For example: __vtbl__3foo (foo virtual table) __vtbl__3foo__3bar (bar::foo virtual table) */ static int arm_special (mangled, declp) const char **mangled; string *declp; { int n; int success = 1; const char *scan; if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0) { /* Found a ARM style virtual table, get past ARM_VTABLE_STRING and create the decl. Note that we consume the entire mangled input string, which means that demangle_signature has no work to do. */ scan = *mangled + ARM_VTABLE_STRLEN; while (*scan != '\0') /* first check it can be demangled */ { n = consume_count (&scan); if (n == -1) { return (0); /* no good */ } scan += n; if (scan[0] == '_' && scan[1] == '_') { scan += 2; } } (*mangled) += ARM_VTABLE_STRLEN; while (**mangled != '\0') { n = consume_count (mangled); if (n == -1 || n > (long) strlen (*mangled)) return 0; string_prependn (declp, *mangled, n); (*mangled) += n; if ((*mangled)[0] == '_' && (*mangled)[1] == '_') { string_prepend (declp, "::"); (*mangled) += 2; } } string_append (declp, " virtual table"); } else { success = 0; } return (success); } /* LOCAL FUNCTION demangle_qualified -- demangle 'Q' qualified name strings SYNOPSIS static int demangle_qualified (struct work_stuff *, const char *mangled, string *result, int isfuncname, int append); DESCRIPTION Demangle a qualified name, such as "Q25Outer5Inner" which is the mangled form of "Outer::Inner". The demangled output is prepended or appended to the result string according to the state of the append flag. If isfuncname is nonzero, then the qualified name we are building is going to be used as a member function name, so if it is a constructor or destructor function, append an appropriate constructor or destructor name. I.E. for the above example, the result for use as a constructor is "Outer::Inner::Inner" and the result for use as a destructor is "Outer::Inner::~Inner". BUGS Numeric conversion is ASCII dependent (FIXME). */ static int demangle_qualified (work, mangled, result, isfuncname, append) struct work_stuff *work; const char **mangled; string *result; int isfuncname; int append; { int qualifiers = 0; int success = 1; char num[2]; string temp; string last_name; int bindex = register_Btype (work); /* We only make use of ISFUNCNAME if the entity is a constructor or destructor. */ isfuncname = (isfuncname && ((work->constructor & 1) || (work->destructor & 1))); string_init (&temp); string_init (&last_name); if ((*mangled)[0] == 'K') { /* Squangling qualified name reuse */ int idx; (*mangled)++; idx = consume_count_with_underscores (mangled); if (idx == -1 || idx >= work -> numk) success = 0; else string_append (&temp, work -> ktypevec[idx]); } else switch ((*mangled)[1]) { case '_': /* GNU mangled name with more than 9 classes. The count is preceded by an underscore (to distinguish it from the <= 9 case) and followed by an underscore. */ (*mangled)++; qualifiers = consume_count_with_underscores (mangled); if (qualifiers == -1) success = 0; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* The count is in a single digit. */ num[0] = (*mangled)[1]; num[1] = '\0'; qualifiers = atoi (num); /* If there is an underscore after the digit, skip it. This is said to be for ARM-qualified names, but the ARM makes no mention of such an underscore. Perhaps cfront uses one. */ if ((*mangled)[2] == '_') { (*mangled)++; } (*mangled) += 2; break; case '0': default: success = 0; } if (!success) return success; /* Pick off the names and collect them in the temp buffer in the order in which they are found, separated by '::'. */ while (qualifiers-- > 0) { int remember_K = 1; string_clear (&last_name); if (*mangled[0] == '_') (*mangled)++; if (*mangled[0] == 't') { /* Here we always append to TEMP since we will want to use the template name without the template parameters as a constructor or destructor name. The appropriate (parameter-less) value is returned by demangle_template in LAST_NAME. We do not remember the template type here, in order to match the G++ mangling algorithm. */ success = demangle_template(work, mangled, &temp, &last_name, 1, 0); if (!success) break; } else if (*mangled[0] == 'K') { int idx; (*mangled)++; idx = consume_count_with_underscores (mangled); if (idx == -1 || idx >= work->numk) success = 0; else string_append (&temp, work->ktypevec[idx]); remember_K = 0; if (!success) break; } else { if (EDG_DEMANGLING) { int namelength; /* Now recursively demangle the qualifier * This is necessary to deal with templates in * mangling styles like EDG */ namelength = consume_count (mangled); if (namelength == -1) { success = 0; break; } recursively_demangle(work, mangled, &temp, namelength); } else { string_delete (&last_name); success = do_type (work, mangled, &last_name); if (!success) break; string_appends (&temp, &last_name); } } if (remember_K) remember_Ktype (work, temp.b, LEN_STRING (&temp)); if (qualifiers > 0) string_append (&temp, SCOPE_STRING (work)); } remember_Btype (work, temp.b, LEN_STRING (&temp), bindex); /* If we are using the result as a function name, we need to append the appropriate '::' separated constructor or destructor name. We do this here because this is the most convenient place, where we already have a pointer to the name and the length of the name. */ if (isfuncname) { string_append (&temp, SCOPE_STRING (work)); if (work -> destructor & 1) string_append (&temp, "~"); string_appends (&temp, &last_name); } /* Now either prepend the temp buffer to the result, or append it, depending upon the state of the append flag. */ if (append) string_appends (result, &temp); else { if (!STRING_EMPTY (result)) string_append (&temp, SCOPE_STRING (work)); string_prepends (result, &temp); } string_delete (&last_name); string_delete (&temp); return (success); } /* LOCAL FUNCTION get_count -- convert an ascii count to integer, consuming tokens SYNOPSIS static int get_count (const char **type, int *count) DESCRIPTION Assume that *type points at a count in a mangled name; set *count to its value, and set *type to the next character after the count. There are some weird rules in effect here. If *type does not point at a string of digits, return zero. If *type points at a string of digits followed by an underscore, set *count to their value as an integer, advance *type to point *after the underscore, and return 1. If *type points at a string of digits not followed by an underscore, consume only the first digit. Set *count to its value as an integer, leave *type pointing after that digit, and return 1. The excuse for this odd behavior: in the ARM and HP demangling styles, a type can be followed by a repeat count of the form `Nxy', where: `x' is a single digit specifying how many additional copies of the type to append to the argument list, and `y' is one or more digits, specifying the zero-based index of the first repeated argument in the list. Yes, as you're unmangling the name you can figure this out yourself, but it's there anyway. So, for example, in `bar__3fooFPiN51', the first argument is a pointer to an integer (`Pi'), and then the next five arguments are the same (`N5'), and the first repeat is the function's second argument (`1'). */ static int get_count (type, count) const char **type; int *count; { const char *p; int n; if (!g_ascii_isdigit ((unsigned char)**type)) return (0); else { *count = **type - '0'; (*type)++; if (g_ascii_isdigit ((unsigned char)**type)) { p = *type; n = *count; do { n *= 10; n += *p - '0'; p++; } while (g_ascii_isdigit ((unsigned char)*p)); if (*p == '_') { *type = p + 1; *count = n; } } } return (1); } /* RESULT will be initialised here; it will be freed on failure. The value returned is really a type_kind_t. */ static int do_type (work, mangled, result) struct work_stuff *work; const char **mangled; string *result; { int n; int done; int success; string decl; const char *remembered_type; int type_quals; type_kind_t tk = tk_none; string_init (&decl); string_init (result); done = 0; success = 1; while (success && !done) { int member; switch (**mangled) { /* A pointer type */ case 'P': case 'p': (*mangled)++; if (! (work -> options & DMGL_JAVA)) string_prepend (&decl, "*"); if (tk == tk_none) tk = tk_pointer; break; /* A reference type */ case 'R': (*mangled)++; string_prepend (&decl, "&"); if (tk == tk_none) tk = tk_reference; break; /* An array */ case 'A': { ++(*mangled); if (!STRING_EMPTY (&decl) && (decl.b[0] == '*' || decl.b[0] == '&')) { string_prepend (&decl, "("); string_append (&decl, ")"); } string_append (&decl, "["); if (**mangled != '_') success = demangle_template_value_parm (work, mangled, &decl, tk_integral); if (**mangled == '_') ++(*mangled); string_append (&decl, "]"); break; } /* A back reference to a previously seen type */ case 'T': (*mangled)++; if (!get_count (mangled, &n) || n >= work -> ntypes) { success = 0; } else { remembered_type = work -> typevec[n]; mangled = &remembered_type; } break; /* A function */ case 'F': (*mangled)++; if (!STRING_EMPTY (&decl) && (decl.b[0] == '*' || decl.b[0] == '&')) { string_prepend (&decl, "("); string_append (&decl, ")"); } /* After picking off the function args, we expect to either find the function return type (preceded by an '_') or the end of the string. */ if (!demangle_nested_args (work, mangled, &decl) || (**mangled != '_' && **mangled != '\0')) { success = 0; break; } if (success && (**mangled == '_')) (*mangled)++; break; case 'M': case 'O': { type_quals = TYPE_UNQUALIFIED; member = **mangled == 'M'; (*mangled)++; string_append (&decl, ")"); /* We don't need to prepend `::' for a qualified name; demangle_qualified will do that for us. */ if (**mangled != 'Q') string_prepend (&decl, SCOPE_STRING (work)); if (g_ascii_isdigit ((unsigned char)**mangled)) { n = consume_count (mangled); if (n == -1 || (int) strlen (*mangled) < n) { success = 0; break; } string_prependn (&decl, *mangled, n); *mangled += n; } else if (**mangled == 'X' || **mangled == 'Y') { string temp; do_type (work, mangled, &temp); string_prepends (&decl, &temp); string_delete (&temp); } else if (**mangled == 't') { string temp; string_init (&temp); success = demangle_template (work, mangled, &temp, NULL, 1, 1); if (success) { string_prependn (&decl, temp.b, temp.p - temp.b); string_delete (&temp); } else break; } else if (**mangled == 'Q') { success = demangle_qualified (work, mangled, &decl, /*isfuncnam=*/0, /*append=*/0); if (!success) break; } else { success = 0; break; } string_prepend (&decl, "("); if (member) { switch (**mangled) { case 'C': case 'V': case 'u': type_quals |= code_for_qualifier (**mangled); (*mangled)++; break; default: break; } if (*(*mangled)++ != 'F') { success = 0; break; } } if ((member && !demangle_nested_args (work, mangled, &decl)) || **mangled != '_') { success = 0; break; } (*mangled)++; if (! PRINT_ANSI_QUALIFIERS) { break; } if (type_quals != TYPE_UNQUALIFIED) { APPEND_BLANK (&decl); string_append (&decl, qualifier_string (type_quals)); } break; } case 'G': (*mangled)++; break; case 'C': case 'V': case 'u': if (PRINT_ANSI_QUALIFIERS) { if (!STRING_EMPTY (&decl)) string_prepend (&decl, " "); string_prepend (&decl, demangle_qualifier (**mangled)); } (*mangled)++; break; /* } */ /* fall through */ default: done = 1; break; } } if (success) switch (**mangled) { /* A qualified name, such as "Outer::Inner". */ case 'Q': case 'K': { success = demangle_qualified (work, mangled, result, 0, 1); break; } /* A back reference to a previously seen squangled type */ case 'B': (*mangled)++; if (!get_count (mangled, &n) || n >= work -> numb) success = 0; else string_append (result, work->btypevec[n]); break; case 'X': case 'Y': /* A template parm. We substitute the corresponding argument. */ { int idx; (*mangled)++; idx = consume_count_with_underscores (mangled); if (idx == -1 || (work->tmpl_argvec && idx >= work->ntmpl_args) || consume_count_with_underscores (mangled) == -1) { success = 0; break; } if (work->tmpl_argvec) string_append (result, work->tmpl_argvec[idx]); else string_append_template_idx (result, idx); success = 1; } break; default: success = demangle_fund_type (work, mangled, result); if (tk == tk_none) tk = (type_kind_t) success; break; } if (success) { if (!STRING_EMPTY (&decl)) { string_append (result, " "); string_appends (result, &decl); } } else string_delete (result); string_delete (&decl); if (success) /* Assume an integral type, if we're not sure. */ return (int) ((tk == tk_none) ? tk_integral : tk); else return 0; } /* Given a pointer to a type string that represents a fundamental type argument (int, long, unsigned int, etc) in TYPE, a pointer to the string in which the demangled output is being built in RESULT, and the WORK structure, decode the types and add them to the result. For example: "Ci" => "const int" "Sl" => "signed long" "CUs" => "const unsigned short" The value returned is really a type_kind_t. */ static int demangle_fund_type (work, mangled, result) struct work_stuff *work; const char **mangled; string *result; { int done = 0; int success = 1; char buf[10]; unsigned int dec = 0; type_kind_t tk = tk_integral; /* First pick off any type qualifiers. There can be more than one. */ while (!done) { switch (**mangled) { case 'C': case 'V': case 'u': if (PRINT_ANSI_QUALIFIERS) { if (!STRING_EMPTY (result)) string_prepend (result, " "); string_prepend (result, demangle_qualifier (**mangled)); } (*mangled)++; break; case 'U': (*mangled)++; APPEND_BLANK (result); string_append (result, "unsigned"); break; case 'S': /* signed char only */ (*mangled)++; APPEND_BLANK (result); string_append (result, "signed"); break; case 'J': (*mangled)++; APPEND_BLANK (result); string_append (result, "__complex"); break; default: done = 1; break; } } /* Now pick off the fundamental type. There can be only one. */ switch (**mangled) { case '\0': case '_': break; case 'v': (*mangled)++; APPEND_BLANK (result); string_append (result, "void"); break; case 'x': (*mangled)++; APPEND_BLANK (result); string_append (result, "long long"); break; case 'l': (*mangled)++; APPEND_BLANK (result); string_append (result, "long"); break; case 'i': (*mangled)++; APPEND_BLANK (result); string_append (result, "int"); break; case 's': (*mangled)++; APPEND_BLANK (result); string_append (result, "short"); break; case 'b': (*mangled)++; APPEND_BLANK (result); string_append (result, "bool"); tk = tk_bool; break; case 'c': (*mangled)++; APPEND_BLANK (result); string_append (result, "char"); tk = tk_char; break; case 'w': (*mangled)++; APPEND_BLANK (result); string_append (result, "wchar_t"); tk = tk_char; break; case 'r': (*mangled)++; APPEND_BLANK (result); string_append (result, "long double"); tk = tk_real; break; case 'd': (*mangled)++; APPEND_BLANK (result); string_append (result, "double"); tk = tk_real; break; case 'f': (*mangled)++; APPEND_BLANK (result); string_append (result, "float"); tk = tk_real; break; case 'G': (*mangled)++; if (!g_ascii_isdigit ((unsigned char)**mangled)) { success = 0; break; } case 'I': (*mangled)++; if (**mangled == '_') { int i; (*mangled)++; for (i = 0; i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_'; (*mangled)++, i++) buf[i] = **mangled; if (**mangled != '_') { success = 0; break; } buf[i] = '\0'; (*mangled)++; } else { strncpy (buf, *mangled, 2); buf[2] = '\0'; *mangled += min (strlen (*mangled), 2); } sscanf (buf, "%x", &dec); sprintf (buf, "int%u_t", dec); APPEND_BLANK (result); string_append (result, buf); break; /* fall through */ /* An explicit type, such as "6mytype" or "7integer" */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int bindex = register_Btype (work); string btype; string_init (&btype); if (demangle_class_name (work, mangled, &btype)) { remember_Btype (work, btype.b, LEN_STRING (&btype), bindex); APPEND_BLANK (result); string_appends (result, &btype); } else success = 0; string_delete (&btype); break; } case 't': { string btype; string_init (&btype); success = demangle_template (work, mangled, &btype, 0, 1, 1); string_appends (result, &btype); string_delete (&btype); break; } default: success = 0; break; } return success ? ((int) tk) : 0; } /* Handle a template's value parameter for HP aCC (extension from ARM) **mangled points to 'S' or 'U' */ static int do_hpacc_template_const_value (work, mangled, result) struct work_stuff *work ATTRIBUTE_UNUSED; const char **mangled; string *result; { int unsigned_const; if (**mangled != 'U' && **mangled != 'S') return 0; unsigned_const = (**mangled == 'U'); (*mangled)++; switch (**mangled) { case 'N': string_append (result, "-"); /* fall through */ case 'P': (*mangled)++; break; case 'M': /* special case for -2^31 */ string_append (result, "-2147483648"); (*mangled)++; return 1; default: return 0; } /* We have to be looking at an integer now */ if (!(g_ascii_isdigit ((unsigned char)**mangled))) return 0; /* We only deal with integral values for template parameters -- so it's OK to look only for digits */ while (g_ascii_isdigit ((unsigned char)**mangled)) { char_str[0] = **mangled; string_append (result, char_str); (*mangled)++; } if (unsigned_const) string_append (result, "U"); /* FIXME? Some day we may have 64-bit (or larger :-) ) constants with L or LL suffixes. pai/1997-09-03 */ return 1; /* success */ } /* Handle a template's literal parameter for HP aCC (extension from ARM) **mangled is pointing to the 'A' */ static int do_hpacc_template_literal (work, mangled, result) struct work_stuff *work; const char **mangled; string *result; { int literal_len = 0; char * recurse; char * recurse_dem; if (**mangled != 'A') return 0; (*mangled)++; literal_len = consume_count (mangled); if (literal_len <= 0) return 0; /* Literal parameters are names of arrays, functions, etc. and the canonical representation uses the address operator */ string_append (result, "&"); /* Now recursively demangle the literal name */ recurse = (char *) g_malloc (literal_len + 1); memcpy (recurse, *mangled, literal_len); recurse[literal_len] = '\000'; recurse_dem = sysprof_cplus_demangle (recurse, work->options); if (recurse_dem) { string_append (result, recurse_dem); g_free (recurse_dem); } else { string_appendn (result, *mangled, literal_len); } (*mangled) += literal_len; g_free (recurse); return 1; } static int snarf_numeric_literal (args, arg) const char ** args; string * arg; { if (**args == '-') { char_str[0] = '-'; string_append (arg, char_str); (*args)++; } else if (**args == '+') (*args)++; if (!g_ascii_isdigit ((unsigned char)**args)) return 0; while (g_ascii_isdigit ((unsigned char)**args)) { char_str[0] = **args; string_append (arg, char_str); (*args)++; } return 1; } /* Demangle the next argument, given by MANGLED into RESULT, which *should be an uninitialized* string. It will be initialized here, and free'd should anything go wrong. */ static int do_arg (work, mangled, result) struct work_stuff *work; const char **mangled; string *result; { /* Remember where we started so that we can record the type, for non-squangling type remembering. */ const char *start = *mangled; string_init (result); if (work->nrepeats > 0) { --work->nrepeats; if (work->previous_argument == 0) return 0; /* We want to reissue the previous type in this argument list. */ string_appends (result, work->previous_argument); return 1; } if (**mangled == 'n') { /* A squangling-style repeat. */ (*mangled)++; work->nrepeats = consume_count(mangled); if (work->nrepeats <= 0) /* This was not a repeat count after all. */ return 0; if (work->nrepeats > 9) { if (**mangled != '_') /* The repeat count should be followed by an '_' in this case. */ return 0; else (*mangled)++; } /* Now, the repeat is all set up. */ return do_arg (work, mangled, result); } /* Save the result in WORK->previous_argument so that we can find it if it's repeated. Note that saving START is not good enough: we do not want to add additional types to the back-referenceable type vector when processing a repeated type. */ if (work->previous_argument) string_delete (work->previous_argument); else work->previous_argument = (string*) g_malloc (sizeof (string)); if (!do_type (work, mangled, work->previous_argument)) return 0; string_appends (result, work->previous_argument); remember_type (work, start, *mangled - start); return 1; } static void remember_type (work, start, len) struct work_stuff *work; const char *start; int len; { char *tem; if (work->forgetting_types) return; if (work -> ntypes >= work -> typevec_size) { if (work -> typevec_size == 0) { work -> typevec_size = 3; work -> typevec = (char **) g_malloc (sizeof (char *) * work -> typevec_size); } else { work -> typevec_size *= 2; work -> typevec = (char **) g_realloc ((char *)work -> typevec, sizeof (char *) * work -> typevec_size); } } tem = g_malloc (len + 1); memcpy (tem, start, len); tem[len] = '\0'; work -> typevec[work -> ntypes++] = tem; } /* Remember a K type class qualifier. */ static void remember_Ktype (work, start, len) struct work_stuff *work; const char *start; int len; { char *tem; if (work -> numk >= work -> ksize) { if (work -> ksize == 0) { work -> ksize = 5; work -> ktypevec = (char **) g_malloc (sizeof (char *) * work -> ksize); } else { work -> ksize *= 2; work -> ktypevec = (char **) g_realloc ((char *)work -> ktypevec, sizeof (char *) * work -> ksize); } } tem = g_malloc (len + 1); memcpy (tem, start, len); tem[len] = '\0'; work -> ktypevec[work -> numk++] = tem; } /* Register a B code, and get an index for it. B codes are registered as they are seen, rather than as they are completed, so map > registers map > as B0, and temp as B1 */ static int register_Btype (work) struct work_stuff *work; { int ret; if (work -> numb >= work -> bsize) { if (work -> bsize == 0) { work -> bsize = 5; work -> btypevec = (char **) g_malloc (sizeof (char *) * work -> bsize); } else { work -> bsize *= 2; work -> btypevec = (char **) g_realloc ((char *)work -> btypevec, sizeof (char *) * work -> bsize); } } ret = work -> numb++; work -> btypevec[ret] = NULL; return(ret); } /* Store a value into a previously registered B code type. */ static void remember_Btype (work, start, len, index) struct work_stuff *work; const char *start; int len, index; { char *tem; tem = g_malloc (len + 1); memcpy (tem, start, len); tem[len] = '\0'; work -> btypevec[index] = tem; } /* Lose all the info related to B and K type codes. */ static void forget_B_and_K_types (work) struct work_stuff *work; { int i; while (work -> numk > 0) { i = --(work -> numk); if (work -> ktypevec[i] != NULL) { g_free (work -> ktypevec[i]); work -> ktypevec[i] = NULL; } } while (work -> numb > 0) { i = --(work -> numb); if (work -> btypevec[i] != NULL) { g_free (work -> btypevec[i]); work -> btypevec[i] = NULL; } } } /* Forget the remembered types, but not the type vector itself. */ static void forget_types (work) struct work_stuff *work; { int i; while (work -> ntypes > 0) { i = --(work -> ntypes); if (work -> typevec[i] != NULL) { g_free (work -> typevec[i]); work -> typevec[i] = NULL; } } } /* Process the argument list part of the signature, after any class spec has been consumed, as well as the first 'F' character (if any). For example: "__als__3fooRT0" => process "RT0" "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i" DECLP must be already initialised, usually non-empty. It won't be freed on failure. Note that g++ differs significantly from ARM and lucid style mangling with regards to references to previously seen types. For example, given the source fragment: class foo { public: foo::foo (int, foo &ia, int, foo &ib, int, foo &ic); }; foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } g++ produces the names: __3fooiRT0iT2iT2 foo__FiR3fooiT1iT1 while lcc (and presumably other ARM style compilers as well) produces: foo__FiR3fooT1T2T1T2 __ct__3fooFiR3fooT1T2T1T2 Note that g++ bases its type numbers starting at zero and counts all previously seen types, while lucid/ARM bases its type numbers starting at one and only considers types after it has seen the 'F' character indicating the start of the function args. For lucid/ARM style, we account for this difference by discarding any previously seen types when we see the 'F' character, and subtracting one from the type number reference. */ static int demangle_args (work, mangled, declp) struct work_stuff *work; const char **mangled; string *declp; { string arg; int need_comma = 0; int r; int t; const char *tem; char temptype; if (PRINT_ARG_TYPES) { string_append (declp, "("); if (**mangled == '\0') { string_append (declp, "void"); } } while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e') || work->nrepeats > 0) { if ((**mangled == 'N') || (**mangled == 'T')) { temptype = *(*mangled)++; if (temptype == 'N') { if (!get_count (mangled, &r)) { return (0); } } else { r = 1; } if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10) { /* If we have 10 or more types we might have more than a 1 digit index so we'll have to consume the whole count here. This will lose if the next thing is a type name preceded by a count but it's impossible to demangle that case properly anyway. Eg if we already have 12 types is T12Pc "(..., type1, Pc, ...)" or "(..., type12, char *, ...)" */ if ((t = consume_count(mangled)) <= 0) { return (0); } } else { if (!get_count (mangled, &t)) { return (0); } } if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) { t--; } /* Validate the type index. Protect against illegal indices from malformed type strings. */ if ((t < 0) || (t >= work -> ntypes)) { return (0); } while (work->nrepeats > 0 || --r >= 0) { tem = work -> typevec[t]; if (need_comma && PRINT_ARG_TYPES) { string_append (declp, ", "); } if (!do_arg (work, &tem, &arg)) { return (0); } if (PRINT_ARG_TYPES) { string_appends (declp, &arg); } string_delete (&arg); need_comma = 1; } } else { if (need_comma && PRINT_ARG_TYPES) string_append (declp, ", "); if (!do_arg (work, mangled, &arg)) return (0); if (PRINT_ARG_TYPES) string_appends (declp, &arg); string_delete (&arg); need_comma = 1; } } if (**mangled == 'e') { (*mangled)++; if (PRINT_ARG_TYPES) { if (need_comma) { string_append (declp, ","); } string_append (declp, "..."); } } if (PRINT_ARG_TYPES) { string_append (declp, ")"); } return (1); } /* Like demangle_args, but for demangling the argument lists of function and method pointers or references, not top-level declarations. */ static int demangle_nested_args (work, mangled, declp) struct work_stuff *work; const char **mangled; string *declp; { string* saved_previous_argument; int result; int saved_nrepeats; /* The G++ name-mangling algorithm does not remember types on nested argument lists, unless -fsquangling is used, and in that case the type vector updated by remember_type is not used. So, we turn off remembering of types here. */ ++work->forgetting_types; /* For the repeat codes used with -fsquangling, we must keep track of the last argument. */ saved_previous_argument = work->previous_argument; saved_nrepeats = work->nrepeats; work->previous_argument = 0; work->nrepeats = 0; /* Actually demangle the arguments. */ result = demangle_args (work, mangled, declp); /* Restore the previous_argument field. */ if (work->previous_argument) { string_delete (work->previous_argument); g_free ((char *) work->previous_argument); } work->previous_argument = saved_previous_argument; --work->forgetting_types; work->nrepeats = saved_nrepeats; return result; } static void demangle_function_name (work, mangled, declp, scan) struct work_stuff *work; const char **mangled; string *declp; const char *scan; { size_t i; string type; const char *tem; string_appendn (declp, (*mangled), scan - (*mangled)); string_need (declp, 1); *(declp -> p) = '\0'; /* Consume the function name, including the "__" separating the name from the signature. We are guaranteed that SCAN points to the separator. */ (*mangled) = scan + 2; /* We may be looking at an instantiation of a template function: foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a following _F marks the start of the function arguments. Handle the template arguments first. */ if (HP_DEMANGLING && (**mangled == 'X')) { demangle_arm_hp_template (work, mangled, 0, declp); /* This leaves MANGLED pointing to the 'F' marking func args */ } if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) { /* See if we have an ARM style constructor or destructor operator. If so, then just record it, clear the decl, and return. We can't build the actual constructor/destructor decl until later, when we recover the class name from the signature. */ if (strcmp (declp -> b, "__ct") == 0) { work -> constructor += 1; string_clear (declp); return; } else if (strcmp (declp -> b, "__dt") == 0) { work -> destructor += 1; string_clear (declp); return; } } if (declp->p - declp->b >= 3 && declp->b[0] == 'o' && declp->b[1] == 'p' && strchr (cplus_markers, declp->b[2]) != NULL) { /* see if it's an assignment expression */ if (declp->p - declp->b >= 10 /* op$assign_ */ && memcmp (declp->b + 3, "assign_", 7) == 0) { for (i = 0; i < G_N_ELEMENTS (optable); i++) { int len = declp->p - declp->b - 10; if ((int) strlen (optable[i].in) == len && memcmp (optable[i].in, declp->b + 10, len) == 0) { string_clear (declp); string_append (declp, "operator"); string_append (declp, optable[i].out); string_append (declp, "="); break; } } } else { for (i = 0; i < G_N_ELEMENTS (optable); i++) { int len = declp->p - declp->b - 3; if ((int) strlen (optable[i].in) == len && memcmp (optable[i].in, declp->b + 3, len) == 0) { string_clear (declp); string_append (declp, "operator"); string_append (declp, optable[i].out); break; } } } } else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0 && strchr (cplus_markers, declp->b[4]) != NULL) { /* type conversion operator */ tem = declp->b + 5; if (do_type (work, &tem, &type)) { string_clear (declp); string_append (declp, "operator "); string_appends (declp, &type); string_delete (&type); } } else if (declp->b[0] == '_' && declp->b[1] == '_' && declp->b[2] == 'o' && declp->b[3] == 'p') { /* ANSI. */ /* type conversion operator. */ tem = declp->b + 4; if (do_type (work, &tem, &type)) { string_clear (declp); string_append (declp, "operator "); string_appends (declp, &type); string_delete (&type); } } else if (declp->b[0] == '_' && declp->b[1] == '_' && g_ascii_islower((unsigned char)declp->b[2]) && g_ascii_islower((unsigned char)declp->b[3])) { if (declp->b[4] == '\0') { /* Operator. */ for (i = 0; i < G_N_ELEMENTS (optable); i++) { if (strlen (optable[i].in) == 2 && memcmp (optable[i].in, declp->b + 2, 2) == 0) { string_clear (declp); string_append (declp, "operator"); string_append (declp, optable[i].out); break; } } } else { if (declp->b[2] == 'a' && declp->b[5] == '\0') { /* Assignment. */ for (i = 0; i < G_N_ELEMENTS (optable); i++) { if (strlen (optable[i].in) == 3 && memcmp (optable[i].in, declp->b + 2, 3) == 0) { string_clear (declp); string_append (declp, "operator"); string_append (declp, optable[i].out); break; } } } } } } /* a mini string-handling package */ static void string_need (s, n) string *s; int n; { int tem; if (s->b == NULL) { if (n < 32) { n = 32; } s->p = s->b = g_malloc (n); s->e = s->b + n; } else if (s->e - s->p < n) { tem = s->p - s->b; n += tem; n *= 2; s->b = g_realloc (s->b, n); s->p = s->b + tem; s->e = s->b + n; } } static void string_delete (s) string *s; { if (s->b != NULL) { g_free (s->b); s->b = s->e = s->p = NULL; } } static void string_init (s) string *s; { s->b = s->p = s->e = NULL; } static void string_clear (s) string *s; { s->p = s->b; } #if 0 static int string_empty (s) string *s; { return (s->b == s->p); } #endif static void string_append (p, s) string *p; const char *s; { int n; if (s == NULL || *s == '\0') return; n = strlen (s); string_need (p, n); memcpy (p->p, s, n); p->p += n; } static void string_appends (p, s) string *p, *s; { int n; if (s->b != s->p) { n = s->p - s->b; string_need (p, n); memcpy (p->p, s->b, n); p->p += n; } } static void string_appendn (p, s, n) string *p; const char *s; int n; { if (n != 0) { string_need (p, n); memcpy (p->p, s, n); p->p += n; } } static void string_prepend (p, s) string *p; const char *s; { if (s != NULL && *s != '\0') { string_prependn (p, s, strlen (s)); } } static void string_prepends (p, s) string *p, *s; { if (s->b != s->p) { string_prependn (p, s->b, s->p - s->b); } } static void string_prependn (p, s, n) string *p; const char *s; int n; { char *q; if (n != 0) { string_need (p, n); for (q = p->p - 1; q >= p->b; q--) { q[n] = q[0]; } memcpy (p->b, s, n); p->p += n; } } static void string_append_template_idx (s, idx) string *s; int idx; { char buf[INTBUF_SIZE + 1 /* 'T' */]; sprintf(buf, "T%d", idx); string_append (s, buf); } sysprof-1.2.0/NEWS0000644000175000017500000000040412021176713010635 00000000000000- New 'everything' object - New commandline version [Lorenzo Colitti] - Assign time spent in kernel to the user process responsible - New screenshot window - Device based on udev [Kristian Hoegsberg] - Port to RHEL4 [Bastien Nocera] - Performance improvements sysprof-1.2.0/README0000644000175000017500000000624012021176713011022 00000000000000Sysprof is a sampling profiler that uses a kernel module to generate stacktraces which are then interpreted by the userspace program "sysprof". See the Sysprof homepage: http://www.daimi.au.dk/~sandmann/sysprof/ for more information Please mail bug reports to Soren Sandmann (sandmann@daimi.au.dk) Also information about whether it works or doesn't work on your distribution would be appreciated. Requirements: - A Linux kernel version 2.6.9 or newer, compiled with profiling support, is required. - GTK+ 2.6.0 or newer is required - libglade 2.5.1 or newer is required Compiling: - Sysprof must be compiled with the same compiler that compiled the kernel it is going to be used with. Usually this is just the the system compiler, but if you have upgraded your kernel it is possible that the new kernel was compiled with a different compiler If the module is compiled with a different compiler than the one compiling the kernel, "modprobe sysprof-module" will produce this error message: insmod: error inserting './sysprof-module.o': -1 Invalid module format Debugging symbols - The programs and libraries you want to profile should have debugging symbols, or you won't get much usable information. On a Fedora Core system, installing the relevant -debuginfo package should be sufficient. On Ubuntu and Debian, the debug packages are called -dbg. - X server The X server as shipped by most distributions uses its own home-rolled module loading system and Sysprof has no way to deal with that, so if you run sysprof with your normal X server you won't get any information about how time is spent inside the X server. On Ubuntu and Debian there is a package, xserver-xorg-dbg, containing a binary called Xorg-debug that is built in such a way that sysprof can use it. On other systems, to get an X server with usable symbols you have to compile your own: (1) Compile the X server to use ".so" modules: - Uncomment the line "MakeDllModules Yes" in xc/config/cf/xorgsite.def. If you are compiling the CVS version of the X server (the one that will eventually become 6.9), then this is already the default. - "make World" - Don't run "make install" yet. (See below). (2) Make sure the new X server can't see any old ".a" files lying around. If you install on top of an existing installation, just do find /usr/X11R6/lib/"*.a" | sudo xargs rm then run "make install" as root to install the newly compiled X server. If a ".so" X server finds .a files in its module path it will try to load those in preference to .so files and this causes symbol resolution problems (3) Run your new X server (4) Run sysprof as root. This is necessary because the X server binary for security reasons is not readable by regular users. I could tell you why, but then I'd have to kill you. Credits: Lorenzo Colitti for writing the sysprof-text program Diana Fong for the icon Mike Frysinger for x86-64 support Kristian Hgsberg for the first port to the 2.6 kernel. Owen Taylor for the symbol lookup code in memprof Sren (sandmann@daimi.au.dk) sysprof-1.2.0/sysprof.c0000644000175000017500000011651712021176713012024 00000000000000/* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, Red Hat, Inc. * Copyright 2004, 2005, 2006, 2007, 2008, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include "footreestore.h" #include "treeviewutils.h" #include "profile.h" #include "collector.h" /* FIXME - not10 */ #define _(a) a #define APPLICATION_NAME "System Profiler" typedef struct Application Application; typedef enum { INITIAL, DISPLAYING, PROFILING } State; struct Application { Collector * collector; State state; GdkPixbuf * icon; GtkWidget * main_window; GtkTreeView * object_view; GtkTreeView * callers_view; GtkTreeView * descendants_view; GtkWidget * start_button; GtkWidget * profile_button; GtkWidget * reset_button; GtkWidget * save_as_button; GtkWidget * dummy_button; GtkWidget * start_item; GtkWidget * profile_item; GtkWidget * reset_item; GtkWidget * save_as_item; GtkWidget * open_item; GtkWidget * screenshot_item; GtkWidget * about_item; GtkWidget * quit_item; GtkWidget * hpaned; GtkWidget * vpaned; GtkTreeSelection * object_selection; GtkWidget * samples_label; GtkWidget * samples_hbox; gboolean screenshot_window_visible; GtkWidget * screenshot_textview; GtkWidget * screenshot_close_button; GtkWidget * screenshot_window; Profile * profile; ProfileDescendant * descendants; ProfileCaller * callers; int timeout_id; int update_screenshot_id; char * loaded_profile; gboolean inhibit_forced_redraw; }; static void update_screenshot_window (Application *app); static void show_samples (Application *app) { char *label; int n_samples; switch (app->state) { case INITIAL: n_samples = 0; break; case PROFILING: n_samples = collector_get_n_samples (app->collector); break; case DISPLAYING: n_samples = profile_get_size (app->profile); break; default: g_assert_not_reached(); break; } label = g_strdup_printf ("%d", n_samples); gtk_label_set_label (GTK_LABEL (app->samples_label), label); g_free (label); } static gboolean show_samples_timeout (gpointer data) { Application *app = data; show_samples (app); app->timeout_id = 0; return FALSE; } static void queue_show_samples (Application *app) { if (!app->timeout_id) app->timeout_id = g_timeout_add (225, show_samples_timeout, app); } static void update_sensitivity (Application *app) { gboolean sensitive_profile_button; gboolean sensitive_save_as_button; gboolean sensitive_start_button; gboolean sensitive_tree_views; gboolean sensitive_samples_hbox; gboolean sensitive_reset_button; GtkWidget *active_radio_button; gboolean has_samples; switch (app->state) { case INITIAL: sensitive_profile_button = FALSE; sensitive_save_as_button = FALSE; sensitive_start_button = TRUE; sensitive_reset_button = FALSE; sensitive_tree_views = FALSE; sensitive_samples_hbox = FALSE; active_radio_button = app->dummy_button; break; case PROFILING: has_samples = (collector_get_n_samples (app->collector) > 0); sensitive_profile_button = has_samples; sensitive_save_as_button = has_samples; sensitive_reset_button = has_samples; sensitive_start_button = TRUE; sensitive_tree_views = FALSE; sensitive_samples_hbox = TRUE; active_radio_button = app->start_button; break; case DISPLAYING: sensitive_profile_button = TRUE; sensitive_save_as_button = TRUE; sensitive_start_button = TRUE; sensitive_tree_views = TRUE; sensitive_reset_button = TRUE; sensitive_samples_hbox = FALSE; active_radio_button = app->profile_button; break; default: g_assert_not_reached(); break; } gtk_toggle_tool_button_set_active ( GTK_TOGGLE_TOOL_BUTTON (active_radio_button), TRUE); /* "profile" widgets */ gtk_widget_set_sensitive (GTK_WIDGET (app->profile_button), sensitive_profile_button); gtk_widget_set_sensitive (GTK_WIDGET (app->profile_item), sensitive_profile_button); /* "save as" widgets */ gtk_widget_set_sensitive (GTK_WIDGET (app->save_as_button), sensitive_save_as_button); gtk_widget_set_sensitive (app->save_as_item, sensitive_save_as_button); /* "start" widgets */ gtk_widget_set_sensitive (GTK_WIDGET (app->start_button), sensitive_start_button); gtk_widget_set_sensitive (GTK_WIDGET (app->start_item), sensitive_start_button); #if 0 /* FIXME - not10: gtk+ doesn't handle changes in sensitivity in response * to a click on the same button very well */ gtk_widget_set_sensitive (GTK_WIDGET (app->reset_button), sensitive_reset_button); gtk_widget_set_sensitive (GTK_WIDGET (app->reset_item), sensitive_reset_button); #endif gtk_widget_set_sensitive (GTK_WIDGET (app->object_view), sensitive_tree_views); gtk_widget_set_sensitive (GTK_WIDGET (app->callers_view), sensitive_tree_views); gtk_widget_set_sensitive (GTK_WIDGET (app->descendants_view), sensitive_tree_views); gtk_widget_set_sensitive (GTK_WIDGET (app->samples_hbox), sensitive_samples_hbox); if (app->screenshot_window_visible) gtk_widget_show (app->screenshot_window); else gtk_widget_hide (app->screenshot_window); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (app->screenshot_item), app->screenshot_window_visible); show_samples (app); } static void set_busy (GtkWidget *widget, gboolean busy) { GdkCursor *cursor; GdkWindow *window; if (busy) cursor = gdk_cursor_new (GDK_WATCH); else cursor = NULL; if (GTK_IS_TEXT_VIEW (widget)) window = gtk_text_view_get_window (GTK_TEXT_VIEW (widget), GTK_TEXT_WINDOW_TEXT); else window = widget->window; gdk_window_set_cursor (window, cursor); if (cursor) gdk_cursor_unref (cursor); gdk_flush(); } static void set_application_title (Application *app, const char * name) { char *new_name; if (name) new_name = g_path_get_basename (name); else new_name = NULL; if (app->loaded_profile) g_free (app->loaded_profile); app->loaded_profile = new_name; if (app->loaded_profile) { gtk_window_set_title (GTK_WINDOW (app->main_window), app->loaded_profile); } else { gtk_window_set_title (GTK_WINDOW (app->main_window), APPLICATION_NAME); } } static void delete_data (Application *app) { if (app->profile) { profile_free (app->profile); app->profile = NULL; gtk_tree_view_set_model (GTK_TREE_VIEW (app->object_view), NULL); gtk_tree_view_set_model (GTK_TREE_VIEW (app->callers_view), NULL); gtk_tree_view_set_model (GTK_TREE_VIEW (app->descendants_view), NULL); } collector_reset (app->collector); set_application_title (app, NULL); } static void sorry (GtkWidget *parent_window, const gchar *format, ...) { va_list args; char *message; GtkWidget *dialog; va_start (args, format); g_vasprintf (&message, format, args); va_end (args); dialog = gtk_message_dialog_new (parent_window ? GTK_WINDOW (parent_window) : NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "%s", message); g_free (message); gtk_window_set_title (GTK_WINDOW (dialog), APPLICATION_NAME " Warning"); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } static void on_menu_item_activated (GtkWidget *menu_item, GtkWidget *tool_button) { GtkToggleToolButton *button = GTK_TOGGLE_TOOL_BUTTON (tool_button); if (!gtk_toggle_tool_button_get_active (button)) gtk_toggle_tool_button_set_active (button, TRUE); } static void on_start_toggled (GtkWidget *widget, gpointer data) { Application *app = data; GError *err = NULL; if (!gtk_toggle_tool_button_get_active ( GTK_TOGGLE_TOOL_BUTTON (app->start_button))) { return; } if (collector_start (app->collector, -1, &err)) { delete_data (app); app->state = PROFILING; } else { sorry (app->main_window, err->message); g_error_free (err); } update_screenshot_window (app); update_sensitivity (app); } enum { OBJECT_NAME, OBJECT_SELF, OBJECT_TOTAL, OBJECT_OBJECT }; enum { CALLERS_NAME, CALLERS_SELF, CALLERS_TOTAL, CALLERS_OBJECT }; enum { DESCENDANTS_NAME, DESCENDANTS_SELF, DESCENDANTS_CUMULATIVE, DESCENDANTS_OBJECT }; static char * get_current_object (Application *app) { GtkTreeModel *model; GtkTreeIter selected; char *object; if (gtk_tree_selection_get_selected (app->object_selection, &model, &selected)) { gtk_tree_model_get (model, &selected, OBJECT_OBJECT, &object, -1); return object; } else { return NULL; } } static void fill_main_list (Application *app) { GList *list; GtkListStore *list_store; Profile *profile = app->profile; GList *objects; if (profile) { list_store = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_POINTER); objects = profile_get_objects (profile); for (list = objects; list != NULL; list = list->next) { ProfileObject *object = list->data; GtkTreeIter iter; double profile_size = profile_get_size (profile); gtk_list_store_append (list_store, &iter); gtk_list_store_set (list_store, &iter, OBJECT_NAME, object->name, OBJECT_SELF, 100.0 * object->self / profile_size, OBJECT_TOTAL, 100.0 * object->total / profile_size, #if 0 OBJECT_SELF, (double)object->self, OBJECT_TOTAL, (double)object->total, #endif OBJECT_OBJECT, object->name, -1); } g_list_foreach (objects, (GFunc)g_free, NULL); g_list_free (objects); tree_view_set_model_with_default_sort (app->object_view, GTK_TREE_MODEL (list_store), OBJECT_TOTAL, GTK_SORT_DESCENDING); g_object_unref (G_OBJECT (list_store)); } gtk_tree_view_columns_autosize (app->object_view); } static void add_node (FooTreeStore *store, int size, const GtkTreeIter *parent, ProfileDescendant *node) { GtkTreeIter iter; if (!node) return; foo_tree_store_insert (store, &iter, (GtkTreeIter *)parent, 0); foo_tree_store_set (store, &iter, DESCENDANTS_NAME, node->name, DESCENDANTS_SELF, 100 * (node->self)/(double)size, DESCENDANTS_CUMULATIVE, 100 * (node->cumulative)/(double)size, #if 0 DESCENDANTS_SELF, (double)node->self, DESCENDANTS_CUMULATIVE, (double)node->non_recursion, #endif DESCENDANTS_OBJECT, node->name, -1); add_node (store, size, parent, node->siblings); add_node (store, size, &iter, node->children); } static void fill_descendants_tree (Application *app) { FooTreeStore *tree_store; if (app->descendants) { profile_descendant_free (app->descendants); app->descendants = NULL; } tree_store = foo_tree_store_new (4, G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_POINTER); if (app->profile) { char *object = get_current_object (app); if (object) { app->descendants = profile_create_descendants (app->profile, object); add_node (tree_store, profile_get_size (app->profile), NULL, app->descendants); } } tree_view_set_model_with_default_sort (app->descendants_view, GTK_TREE_MODEL (tree_store), DESCENDANTS_CUMULATIVE, GTK_SORT_DESCENDING); g_object_unref (G_OBJECT (tree_store)); gtk_tree_view_columns_autosize (app->descendants_view); } static void add_callers (GtkListStore *list_store, Profile *profile, ProfileCaller *callers) { while (callers) { gchar *name; GtkTreeIter iter; double profile_size = profile_get_size (profile); if (callers->name) name = callers->name; else name = ""; gtk_list_store_append (list_store, &iter); gtk_list_store_set ( list_store, &iter, CALLERS_NAME, name, CALLERS_SELF, 100.0 * callers->self / profile_size, CALLERS_TOTAL, 100.0 * callers->total / profile_size, #if 0 CALLERS_SELF, (double)callers->self, CALLERS_TOTAL, (double)callers->total, #endif CALLERS_OBJECT, callers->name, -1); callers = callers->next; } } static void fill_callers_list (Application *app) { GtkListStore *list_store; if (app->callers) { profile_caller_free (app->callers); app->callers = NULL; } list_store = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_POINTER); if (app->profile) { char *object = get_current_object (app); if (object) { app->callers = profile_list_callers (app->profile, object); add_callers (list_store, app->profile, app->callers); } } tree_view_set_model_with_default_sort (app->callers_view, GTK_TREE_MODEL (list_store), CALLERS_TOTAL, GTK_SORT_DESCENDING); g_object_unref (G_OBJECT (list_store)); gtk_tree_view_columns_autosize (app->callers_view); } static void enter_display_mode (Application *app) { app->state = DISPLAYING; update_sensitivity (app); app->inhibit_forced_redraw = TRUE; fill_main_list (app); /* This has the side effect of selecting the first row, which in turn causes * the other lists to be filled out */ gtk_widget_grab_focus (GTK_WIDGET (app->object_view)); app->inhibit_forced_redraw = FALSE; } static void ensure_profile (Application *app) { if (app->profile) return; collector_stop (app->collector); app->profile = collector_create_profile (app->collector); collector_reset (app->collector); enter_display_mode (app); } static void on_about_activated (GtkWidget *widget, gpointer data) { #define OSLASH "\303\270" Application *app = data; char *name_property; if (gtk_minor_version >= 12) name_property = "program-name"; else name_property = "name"; gtk_show_about_dialog (GTK_WINDOW (app->main_window), "logo", app->icon, name_property, APPLICATION_NAME, "copyright", "Copyright 2004-2009, S"OSLASH"ren Sandmann", "version", PACKAGE_VERSION, NULL); } static void on_profile_toggled (GtkWidget *widget, gpointer data) { Application *app = data; if (gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (app->profile_button))) { set_busy (app->main_window, TRUE); ensure_profile (app); set_busy (app->main_window, FALSE); } } static void on_reset_clicked (gpointer widget, gpointer data) { Application *app = data; set_busy (app->main_window, TRUE); delete_data (app); if (app->state == DISPLAYING) { app->state = INITIAL; collector_stop (app->collector); } update_sensitivity (app); set_busy (app->main_window, FALSE); } static gboolean overwrite_file (GtkWindow *window, const char *filename) { GtkWidget *msgbox; gchar *utf8_file_name; AtkObject *obj; gint ret; utf8_file_name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); msgbox = gtk_message_dialog_new (window, (GtkDialogFlags)GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, _("A file named \"%s\" already exists."), utf8_file_name); g_free (utf8_file_name); gtk_message_dialog_format_secondary_text ( GTK_MESSAGE_DIALOG (msgbox), _("Do you want to replace it with the one you are saving?")); gtk_dialog_add_button (GTK_DIALOG (msgbox), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_add_button (GTK_DIALOG (msgbox), _("_Replace"), GTK_RESPONSE_YES); gtk_dialog_set_default_response (GTK_DIALOG (msgbox), GTK_RESPONSE_CANCEL); obj = gtk_widget_get_accessible (msgbox); if (GTK_IS_ACCESSIBLE (obj)) atk_object_set_name (obj, _("Question")); ret = gtk_dialog_run (GTK_DIALOG (msgbox)); gtk_widget_destroy (msgbox); return (ret == GTK_RESPONSE_YES); } static void on_save_as_clicked (gpointer widget, gpointer data) { Application *app = data; GtkWidget *dialog; ensure_profile (app); set_busy (app->main_window, TRUE); dialog = gtk_file_chooser_dialog_new ("Save As", GTK_WINDOW (app->main_window), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); set_busy (app->main_window, FALSE); retry: if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { GError *err = NULL; gchar *filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); if (g_file_test (filename, G_FILE_TEST_EXISTS) && !overwrite_file (GTK_WINDOW (app->main_window), filename)) { g_free (filename); goto retry; } set_busy (dialog, TRUE); if (!profile_save (app->profile, filename, &err)) { sorry (app->main_window, "Could not save %s: %s", filename, err->message); set_busy (dialog, FALSE); g_free (filename); goto retry; } set_application_title (app, filename); set_busy (dialog, FALSE); g_free (filename); } gtk_widget_destroy (dialog); } static void set_loaded_profile (Application *app, const char *name, Profile *profile) { g_return_if_fail (name != NULL); g_return_if_fail (profile != NULL); collector_stop (app->collector); delete_data (app); app->profile = profile; set_application_title (app, name); enter_display_mode (app); } static void show_could_not_open (Application *app, const char *filename, GError *err) { sorry (app->main_window, "Could not open %s: %s", filename, err->message); } static void on_open_clicked (gpointer widget, gpointer data) { Application *app = data; gchar *filename = NULL; Profile *profile = NULL; GtkWidget *dialog; set_busy (app->main_window, TRUE); dialog = gtk_file_chooser_dialog_new ("Open", GTK_WINDOW (app->main_window), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); set_busy (app->main_window, FALSE); retry: if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { GError *err = NULL; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); set_busy (dialog, TRUE); profile = profile_load (filename, &err); if (!profile) { set_busy (dialog, FALSE); show_could_not_open (app, filename, err); g_error_free (err); g_free (filename); filename = NULL; goto retry; } set_busy (dialog, FALSE); } gtk_widget_destroy (dialog); if (profile) { g_assert (filename); set_loaded_profile (app, filename, profile); g_free (filename); } } static void on_delete (GtkWidget *window, Application *app) { /* Workaround for http://bugzilla.gnome.org/show_bug.cgi?id=317775 * * Without it, the read callbacks can fire _after_ gtk_main_quit() * has been called and cause stuff to be called on destroyed widgets. */ while (gtk_main_iteration ()) ; gtk_main_quit (); } static void expand_descendants_tree (Application *app) { GtkTreeModel *model = gtk_tree_view_get_model (app->descendants_view); GtkTreeIter iter; GList *all_paths = NULL; int n_rows; int max_rows = 40; /* FIXME */ double top_value = 0.0; GtkTreePath *first_path; GList *list; first_path = gtk_tree_path_new_first(); all_paths = g_list_prepend (all_paths, first_path); n_rows = 1; gtk_tree_model_get_iter (model, &iter, first_path); gtk_tree_model_get (model, &iter, OBJECT_TOTAL, &top_value, -1); while (all_paths && n_rows < max_rows) { GtkTreeIter best_iter; GtkTreePath *best_path; double best_value; int n_children; int i; best_value = 0.0; best_path = NULL; for (list = all_paths; list != NULL; list = list->next) { GtkTreePath *path = list->data; GtkTreeIter iter; g_assert (path != NULL); if (gtk_tree_model_get_iter (model, &iter, path)) { double value; gtk_tree_model_get (model, &iter, OBJECT_TOTAL, &value, -1); if (value >= best_value) { best_value = value; best_path = path; best_iter = iter; } } } n_children = gtk_tree_model_iter_n_children (model, &best_iter); if (n_children && (best_value / top_value) > 0.04 && (n_children + gtk_tree_path_get_depth (best_path)) / (double)max_rows < (best_value / top_value) ) { gtk_tree_view_expand_row ( GTK_TREE_VIEW (app->descendants_view), best_path, FALSE); n_rows += n_children; if (gtk_tree_path_get_depth (best_path) < 4) { GtkTreePath *path = gtk_tree_path_copy (best_path); gtk_tree_path_down (path); for (i = 0; i < n_children; ++i) { all_paths = g_list_prepend (all_paths, path); path = gtk_tree_path_copy (path); gtk_tree_path_next (path); } gtk_tree_path_free (path); } } all_paths = g_list_remove (all_paths, best_path); if (!all_paths && n_rows == 1) { /* Always expand at least once */ gtk_tree_view_expand_row (GTK_TREE_VIEW (app->descendants_view), best_path, FALSE); } gtk_tree_path_free (best_path); } for (list = all_paths; list != NULL; list = list->next) gtk_tree_path_free (list->data); g_list_free (all_paths); } static void get_data (GtkTreeView *view, GtkTreeIter *iter, gchar **name, double *self, double *cumulative) { char *dummy1; double dummy2; double dummy3; GtkTreeModel *model = gtk_tree_view_get_model (view); gtk_tree_model_get ( model, iter, DESCENDANTS_NAME, name? name : &dummy1, DESCENDANTS_SELF, self? self : &dummy2, DESCENDANTS_CUMULATIVE, cumulative? cumulative : &dummy3, -1); } static int get_indent (GtkTreePath *path) { return 2 * (gtk_tree_path_get_depth (path) - 1); } static void compute_text_width (GtkTreeView *view, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { int *width = data; char *name; get_data (view, iter, &name, NULL, NULL); *width = MAX (g_utf8_strlen (name, -1) + get_indent (path), *width); g_free (name); } typedef struct { int max_width; GString *text; } AddTextInfo; static void set_monospace (GtkWidget *widget) { PangoFontDescription *desc = pango_font_description_from_string ("monospace"); gtk_widget_modify_font (widget, desc); pango_font_description_free (desc); } static void add_text (GtkTreeView *view, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { AddTextInfo *info = data; char *name; double self; double cumulative; int indent; int i; get_data (view, iter, &name, &self, &cumulative); indent = get_indent (path); for (i = 0; i < indent; ++i) g_string_append_c (info->text, ' '); g_string_append_printf (info->text, "%-*s %6.2f%% %6.2f%%\n", info->max_width - indent, name, self, cumulative); g_free (name); } static gboolean update_screenshot_window_idle (gpointer data) { Application *app = data; GtkTextBuffer *text_buffer; if (!app->screenshot_window_visible) return FALSE; text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (app->screenshot_textview)); gtk_text_buffer_set_text (text_buffer, "", -1); if (app->descendants) { AddTextInfo info; info.max_width = 0; info.text = g_string_new (""); tree_view_foreach_visible (app->descendants_view, compute_text_width, &info.max_width); tree_view_foreach_visible (app->descendants_view, add_text, &info); gtk_text_buffer_set_text (text_buffer, info.text->str, -1); set_monospace (app->screenshot_textview); g_string_free (info.text, TRUE); } app->update_screenshot_id = 0; if (app->screenshot_window_visible) { set_busy (app->screenshot_window, FALSE); set_busy (app->screenshot_textview, FALSE); } return FALSE; } static void update_screenshot_window (Application *app) { /* We do this in an idle handler to deal with the case where * someone presses Shift-RightArrow on the root of a huge * profile. This causes a ton of 'expanded' notifications, * each of which would cause us to traverse the tree and * update the screenshot window. */ if (app->update_screenshot_id) g_source_remove (app->update_screenshot_id); if (app->screenshot_window_visible) { /* don't swamp the X server with cursor change requests */ if (!app->update_screenshot_id) { set_busy (app->screenshot_window, TRUE); set_busy (app->screenshot_textview, TRUE); } } app->update_screenshot_id = g_idle_add ( update_screenshot_window_idle, app); } static void on_descendants_row_expanded_or_collapsed (GtkTreeView *tree, GtkTreeIter *iter, GtkTreePath *path, Application *app) { update_screenshot_window (app); } static void on_object_selection_changed (GtkTreeSelection *selection, gpointer data) { Application *app = data; set_busy (app->main_window, TRUE); update_screenshot_window (app); if (!app->inhibit_forced_redraw) gdk_window_process_all_updates (); /* Display updated selection */ fill_descendants_tree (app); fill_callers_list (app); if (get_current_object (app)) expand_descendants_tree (app); set_busy (app->main_window, FALSE); } static void really_goto_object (Application *app, char *object) { GtkTreeModel *profile_objects; GtkTreeIter iter; gboolean found = FALSE; profile_objects = gtk_tree_view_get_model (app->object_view); if (gtk_tree_model_get_iter_first (profile_objects, &iter)) { do { char *list_object; gtk_tree_model_get (profile_objects, &iter, OBJECT_OBJECT, &list_object, -1); if (list_object == object) { found = TRUE; break; } } while (gtk_tree_model_iter_next (profile_objects, &iter)); } if (found) { GtkTreePath *path = gtk_tree_model_get_path (profile_objects, &iter); gtk_tree_view_set_cursor (app->object_view, path, 0, FALSE); } } static void goto_object (Application *app, GtkTreeView *tree_view, GtkTreePath *path, gint column) { GtkTreeIter iter; GtkTreeModel *model = gtk_tree_view_get_model (tree_view); char *object; if (!gtk_tree_model_get_iter (model, &iter, path)) return; gtk_tree_model_get (model, &iter, column, &object, -1); if (!object) return; really_goto_object (app, object); } static void on_descendants_row_activated (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data) { Application *app = data; goto_object (app, tree_view, path, DESCENDANTS_OBJECT); gtk_widget_grab_focus (GTK_WIDGET (app->descendants_view)); } static void on_callers_row_activated (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data) { Application *app = data; goto_object (app, tree_view, path, CALLERS_OBJECT); gtk_widget_grab_focus (GTK_WIDGET (app->callers_view)); } static void on_screenshot_activated (GtkCheckMenuItem *menu_item, Application *app) { app->screenshot_window_visible = gtk_check_menu_item_get_active (menu_item); update_screenshot_window (app); update_sensitivity (app); } static void on_screenshot_window_delete (GtkWidget *window, GdkEvent *event, Application *app) { app->screenshot_window_visible = FALSE; update_sensitivity (app); } static void on_screenshot_close_button_clicked (GtkWidget *widget, Application *app) { app->screenshot_window_visible = FALSE; update_sensitivity (app); } static void set_sizes (GtkWindow *window, GtkWindow *screenshot_window, GtkWidget *hpaned, GtkWidget *vpaned) { GdkScreen *screen; int monitor_num; GdkRectangle monitor; int width, height; GtkWidget *widget = GTK_WIDGET (window); screen = gtk_widget_get_screen (widget); monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window); gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); width = monitor.width * 3 / 4; height = monitor.height * 3 / 4; gtk_window_resize (window, width, height); gtk_paned_set_position (GTK_PANED (vpaned), height / 2); gtk_paned_set_position (GTK_PANED (hpaned), width * 3 / 8); width = monitor.width * 5 / 8; height = monitor.height * 5 / 8; gtk_window_resize (screenshot_window, width, height); } #define GLADE_FILE DATADIR "/sysprof.glade" static void gather_widgets (Application *app) { typedef struct { void *location; const char *name; } WidgetInfo; const WidgetInfo widgets[] = { { &app->main_window, "main_window" }, { &app->start_button, "start_button" }, { &app->profile_button, "profile_button" }, { &app->reset_button, "reset_button" }, { &app->save_as_button, "save_as_button" }, { &app->dummy_button, "dummy_button" }, { &app->samples_label, "samples_label" }, { &app->samples_hbox, "samples_hbox" }, { &app->start_item, "start_item" }, { &app->profile_item, "profile_item" }, { &app->reset_item, "reset_item" }, { &app->open_item, "open_item" }, { &app->save_as_item, "save_as_item" }, { &app->screenshot_item, "screenshot_item" }, { &app->quit_item, "quit" }, { &app->about_item, "about" }, { &app->object_view, "object_view" }, { &app->callers_view, "callers_view" }, { &app->descendants_view, "descendants_view" }, { &app->screenshot_window, "screenshot_window" }, { &app->screenshot_textview, "screenshot_textview" }, { &app->screenshot_close_button, "screenshot_close_button" }, { &app->vpaned, "vpaned" }, { &app->hpaned, "hpaned" }, }; GladeXML *xml = glade_xml_new (GLADE_FILE, NULL, NULL); int i; for (i = 0; i < G_N_ELEMENTS (widgets); ++i) { const WidgetInfo *info = &(widgets[i]); *(GtkWidget **)(info->location) = glade_xml_get_widget (xml, info->name); g_assert (GTK_IS_WIDGET (*(GtkWidget **)info->location)); } g_object_unref (xml); } static void connect_signals (Application *app) { typedef struct { gpointer object; const char *signal; gpointer callback; gpointer data; } SignalInfo; const SignalInfo signals[] = { { app->main_window, "delete_event", on_delete, NULL }, { app->start_button, "toggled", on_start_toggled, app }, { app->profile_button, "toggled", on_profile_toggled, app }, { app->reset_button, "clicked", on_reset_clicked, app }, { app->save_as_button, "clicked", on_save_as_clicked, app }, { app->start_item, "activate", on_menu_item_activated, app->start_button }, { app->profile_item, "activate", on_menu_item_activated, app->profile_button }, { app->reset_item, "activate", on_reset_clicked, app }, { app->open_item, "activate", on_open_clicked, app }, { app->save_as_item, "activate", on_save_as_clicked, app }, { app->screenshot_item, "activate", on_screenshot_activated, app }, { app->quit_item, "activate", on_delete, NULL }, { app->about_item, "activate", on_about_activated, app }, { app->object_selection, "changed", on_object_selection_changed, app }, { app->callers_view, "row-activated", on_callers_row_activated, app }, { app->descendants_view, "row-activated", on_descendants_row_activated, app }, { app->descendants_view, "row-expanded", on_descendants_row_expanded_or_collapsed, app }, { app->descendants_view, "row-collapsed", on_descendants_row_expanded_or_collapsed, app }, { app->screenshot_window, "delete_event", on_screenshot_window_delete, app }, { app->screenshot_close_button, "clicked", on_screenshot_close_button_clicked, app }, }; int i; for (i = 0; i < G_N_ELEMENTS (signals); ++i) { const SignalInfo *info = &(signals[i]); g_signal_connect (info->object, info->signal, info->callback, info->data); } } static void set_shadows (void) { /* Get rid of motif out-bevels */ gtk_rc_parse_string ( "style \"blah\" " "{ " " GtkToolbar::shadow_type = none " " GtkMenuBar::shadow_type = none " " GtkMenuBar::internal_padding = 2 " "} " "widget \"*toolbar\" style : rc \"blah\"\n" "widget \"*menubar\" style : rc \"blah\"\n" ); } static void set_icons (Application *app) { const char *icon_files [] = { PIXMAPDIR "/sysprof-icon-16.png", PIXMAPDIR "/sysprof-icon-24.png", PIXMAPDIR "/sysprof-icon-32.png", PIXMAPDIR "/sysprof-icon-48.png", NULL }; GList *pixbufs = NULL; int i; for (i = 0; icon_files[i] != NULL; ++i) { const char *file = icon_files[i]; GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (file, NULL); if (pixbuf) { pixbufs = g_list_prepend (pixbufs, pixbuf); if (i == 3) /* 48 x 48 */ app->icon = g_object_ref (pixbuf); } else { g_warning ("Could not open %s\n", file); } } gtk_window_set_icon_list (GTK_WINDOW (app->main_window), pixbufs); g_list_foreach (pixbufs, (GFunc)g_object_unref, NULL); g_list_free (pixbufs); } #define PCT_FORMAT "%.2f %%" static gboolean build_gui (Application *app) { GtkTreeViewColumn *col; set_shadows (); if (!g_file_test (GLADE_FILE, G_FILE_TEST_EXISTS)) { sorry (NULL, "Sysprof was not compiled or installed correctly.\n" "\n" "Running \"make install\" may solve this problem.\n"); return FALSE; } gather_widgets (app); g_assert (app->main_window); /* Main Window */ set_icons (app); gtk_widget_realize (GTK_WIDGET (app->main_window)); /* Tool items */ gtk_toggle_tool_button_set_active ( GTK_TOGGLE_TOOL_BUTTON (app->profile_button), FALSE); /* TreeViews */ /* object view */ gtk_tree_view_set_enable_search (app->object_view, FALSE); col = add_plain_text_column (app->object_view, _("Functions"), OBJECT_NAME); add_double_format_column (app->object_view, _("Self"), OBJECT_SELF, PCT_FORMAT); add_double_format_column (app->object_view, _("Total"), OBJECT_TOTAL, PCT_FORMAT); app->object_selection = gtk_tree_view_get_selection (app->object_view); gtk_tree_view_column_set_expand (col, TRUE); /* callers view */ gtk_tree_view_set_enable_search (app->callers_view, FALSE); col = add_plain_text_column (app->callers_view, _("Callers"), CALLERS_NAME); add_double_format_column (app->callers_view, _("Self"), CALLERS_SELF, PCT_FORMAT); add_double_format_column (app->callers_view, _("Total"), CALLERS_TOTAL, PCT_FORMAT); gtk_tree_view_column_set_expand (col, TRUE); /* descendants view */ gtk_tree_view_set_enable_search (app->descendants_view, FALSE); col = add_plain_text_column (app->descendants_view, _("Descendants"), DESCENDANTS_NAME); add_double_format_column (app->descendants_view, _("Self"), DESCENDANTS_SELF, PCT_FORMAT); add_double_format_column (app->descendants_view, _("Cumulative"), DESCENDANTS_CUMULATIVE, PCT_FORMAT); gtk_tree_view_column_set_expand (col, TRUE); /* screenshot window */ /* set sizes */ set_sizes (GTK_WINDOW (app->main_window), GTK_WINDOW (app->screenshot_window), app->hpaned, app->vpaned); /* hide/show widgets */ gtk_widget_show_all (app->main_window); gtk_widget_hide (app->dummy_button); gtk_widget_hide (app->screenshot_window); gtk_widget_grab_focus (GTK_WIDGET (app->object_view)); queue_show_samples (app); connect_signals (app); return TRUE; } static void on_new_sample (gboolean first_sample, gpointer data) { Application *app = data; if (app->state == PROFILING && first_sample) update_sensitivity (app); else queue_show_samples (app); } static Application * application_new (void) { Application *app = g_new0 (Application, 1); app->collector = collector_new (FALSE, on_new_sample, app); app->state = INITIAL; return app; } typedef struct { const char *filename; Application *app; } FileOpenData; static gboolean load_file (gpointer data) { FileOpenData *file_open_data = data; const char *filename = file_open_data->filename; Application *app = file_open_data->app; GError *err = NULL; Profile *profile; set_busy (app->main_window, TRUE); profile = profile_load (filename, &err); if (profile) { set_loaded_profile (app, filename, profile); gdk_window_process_all_updates (); set_busy (app->main_window, FALSE); } else { set_busy (app->main_window, FALSE); show_could_not_open (app, filename, err); g_error_free (err); } g_free (file_open_data); return FALSE; } static const char * process_options (int argc, char **argv) { int i; gboolean show_version = FALSE; const char *filename = NULL; for (i = 1; i < argc; ++i) { char *option = argv[i]; if (strcmp (option, "--version") == 0) { show_version = TRUE; } else if (!filename) { filename = argv[i]; } } if (show_version) { g_print ("%s %s\n", APPLICATION_NAME, PACKAGE_VERSION); exit (1); } return filename; } static void apply_workarounds (void) { /* Disable gslice, since it * * - confuses valgrind * - caches too much memory * - hides memory access bugs * - is not faster than malloc * * Note that g_slice_set_config() is broken in some versions of * GLib (and 'declared internal' according to Tim), so we use the * environment variable instead. */ if (!getenv ("G_SLICE")) putenv ("G_SLICE=always_malloc"); /* Accessibility prevents sysprof from working reliably, so * disable it. Specifically, it * * - causes large amounts of time to be spent in sysprof itself * whenever the label is updated. * - sometimes hangs at shutdown * - does long-running roundtrip requests that prevents * reading the event buffers, resulting in lost events. */ putenv ("NO_GAIL=1"); putenv ("NO_AT_BRIDGE=1"); } int main (int argc, char **argv) { Application *app; const char *filename; apply_workarounds(); filename = process_options (argc, argv); gtk_init (&argc, &argv); app = application_new (); if (!build_gui (app)) return -1; update_sensitivity (app); if (filename) { FileOpenData *file_open_data = g_new0 (FileOpenData, 1); file_open_data->filename = filename; file_open_data->app = app; /* This has to run at G_PRIORITY_LOW because of bug 350517 */ g_idle_add_full (G_PRIORITY_LOW, load_file, file_open_data, NULL); } gtk_main (); return 0; } sysprof-1.2.0/sformat.h0000644000175000017500000000445512021176713011774 00000000000000/* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, Red Hat, Inc. * Copyright 2004, 2005, 2006, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef SFORMAT_H #define SFORMAT_H typedef struct SFormat SFormat; typedef struct SType SType; typedef struct SForward SForward; typedef struct SContext SContext; SFormat *sformat_new (void); void sformat_free (SFormat *format); void sformat_set_type (SFormat *format, SType *type); SForward *sformat_declare_forward (SFormat *format); SType *sformat_make_record (SFormat *format, const char *name, SForward *forward, SType *content, ...); SType *sformat_make_list (SFormat *format, const char *name, SForward *forward, SType *type); SType *sformat_make_pointer (SFormat *format, const char *name, SForward *type); SType *sformat_make_integer (SFormat *format, const char *name); SType *sformat_make_string (SFormat *format, const char *name); gboolean stype_is_record (SType *type); gboolean stype_is_list (SType *type); gboolean stype_is_pointer (SType *type); gboolean stype_is_integer (SType *type); gboolean stype_is_string (SType *type); SType *stype_get_target_type (SType *type); const char *stype_get_name (SType *type); SContext *scontext_new (SFormat *format); SType *scontext_begin (SContext *context, const char *element); SType *scontext_text (SContext *context); SType *scontext_end (SContext *context, const char *element); gboolean scontext_is_finished (SContext *context); void scontext_free (SContext *context); #endif sysprof-1.2.0/footreestore.h0000644000175000017500000001377712021176713013050 00000000000000/* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #ifndef __FOO_TREE_STORE_H__ #define __FOO_TREE_STORE_H__ #include #include G_BEGIN_DECLS #define FOO_TYPE_TREE_STORE (foo_tree_store_get_type ()) #define FOO_TREE_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOO_TYPE_TREE_STORE, FooTreeStore)) #define FOO_TREE_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FOO_TYPE_TREE_STORE, FooTreeStoreClass)) #define FOO_IS_TREE_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOO_TYPE_TREE_STORE)) #define FOO_IS_TREE_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FOO_TYPE_TREE_STORE)) #define FOO_TREE_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FOO_TYPE_TREE_STORE, FooTreeStoreClass)) typedef struct _FooTreeStore FooTreeStore; typedef struct _FooTreeStoreClass FooTreeStoreClass; struct _FooTreeStore { GObject parent; gint stamp; gpointer root; gpointer last; gint n_columns; gint sort_column_id; GList *sort_list; GtkSortType order; GType *column_headers; GtkTreeIterCompareFunc default_sort_func; gpointer default_sort_data; GDestroyNotify default_sort_destroy; guint row_changed_id; guint row_inserted_id; guint row_has_child_toggled_id; guint rows_reordered_id; guint (columns_dirty) : 1; }; struct _FooTreeStoreClass { GObjectClass parent_class; /* Padding for future expansion */ void (*_gtk_reserved1) (void); void (*_gtk_reserved2) (void); void (*_gtk_reserved3) (void); void (*_gtk_reserved4) (void); }; GType foo_tree_store_get_type (void) G_GNUC_CONST; FooTreeStore *foo_tree_store_new (gint n_columns, ...); FooTreeStore *foo_tree_store_newv (gint n_columns, GType *types); void foo_tree_store_set_column_types (FooTreeStore *tree_store, gint n_columns, GType *types); /* NOTE: use gtk_tree_model_get to get values from a FooTreeStore */ void foo_tree_store_set_value (FooTreeStore *tree_store, GtkTreeIter *iter, gint column, GValue *value); void foo_tree_store_set (FooTreeStore *tree_store, GtkTreeIter *iter, ...); void foo_tree_store_set_valuesv (FooTreeStore *tree_store, GtkTreeIter *iter, gint *columns, GValue *values, gint n_values); void foo_tree_store_set_valist (FooTreeStore *tree_store, GtkTreeIter *iter, va_list var_args); gboolean foo_tree_store_remove (FooTreeStore *tree_store, GtkTreeIter *iter); void foo_tree_store_insert (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent, gint position); void foo_tree_store_insert_before (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent, GtkTreeIter *sibling); void foo_tree_store_insert_after (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent, GtkTreeIter *sibling); void foo_tree_store_insert_with_values (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent, gint position, ...); void foo_tree_store_insert_with_valuesv (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent, gint position, gint *columns, GValue *values, gint n_values); void foo_tree_store_prepend (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent); void foo_tree_store_append (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent); gboolean foo_tree_store_is_ancestor (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *descendant); gint foo_tree_store_iter_depth (FooTreeStore *tree_store, GtkTreeIter *iter); void foo_tree_store_clear (FooTreeStore *tree_store); gboolean foo_tree_store_iter_is_valid (FooTreeStore *tree_store, GtkTreeIter *iter); void foo_tree_store_reorder (FooTreeStore *tree_store, GtkTreeIter *parent, gint *new_order); void foo_tree_store_swap (FooTreeStore *tree_store, GtkTreeIter *a, GtkTreeIter *b); void foo_tree_store_move_before (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *position); void foo_tree_store_move_after (FooTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *position); G_END_DECLS #endif /* __FOO_TREE_STORE_H__ */ sysprof-1.2.0/collector.h0000644000175000017500000000325112021176713012300 00000000000000/* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, Red Hat, Inc. * Copyright 2004, 2005, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "profile.h" typedef struct Collector Collector; typedef void (* CollectorFunc) (gboolean first_sample, gpointer data); #define COLLECTOR_ERROR collector_error_quark () GQuark collector_error_quark (void); typedef enum { COLLECTOR_ERROR_FAILED } CollectorError; /* callback is called whenever a new sample arrives */ Collector *collector_new (gboolean use_hw_counters, CollectorFunc callback, gpointer data); gboolean collector_start (Collector *collector, pid_t pid, GError **err); void collector_stop (Collector *collector); void collector_reset (Collector *collector); int collector_get_n_samples (Collector *collector); Profile * collector_create_profile (Collector *collector); sysprof-1.2.0/testdemangle.c0000644000175000017500000000025312021176713012760 00000000000000#include "elfparser.h" int main () { printf ("%s\n", elf_demangle ("_ZN8Inkscape7FiltersL12filter2D_FIRIhLj4EEEvPT_iiPKS2_iiiiPKNS_4Util10FixedPointIjLj16EEEii")); } sysprof-1.2.0/footreedatalist.h0000644000175000017500000000561012021176713013504 00000000000000/* gtktreedatalist.h * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #ifndef __GTK_TREE_DATA_LIST_H__ #define __GTK_TREE_DATA_LIST_H__ #include typedef struct _FooTreeDataList FooTreeDataList; struct _FooTreeDataList { FooTreeDataList *next; union { gint v_int; gint8 v_char; guint8 v_uchar; guint v_uint; glong v_long; gulong v_ulong; gint64 v_int64; guint64 v_uint64; gfloat v_float; gdouble v_double; gpointer v_pointer; } data; }; typedef struct _GtkTreeDataSortHeader { gint sort_column_id; GtkTreeIterCompareFunc func; gpointer data; GDestroyNotify destroy; } GtkTreeDataSortHeader; FooTreeDataList *_foo_tree_data_list_alloc (void); void _foo_tree_data_list_free (FooTreeDataList *list, GType *column_headers); gboolean _foo_tree_data_list_check_type (GType type); void _foo_tree_data_list_node_to_value (FooTreeDataList *list, GType type, GValue *value); void _foo_tree_data_list_value_to_node (FooTreeDataList *list, GValue *value); FooTreeDataList *_foo_tree_data_list_node_copy (FooTreeDataList *list, GType type); /* Header code */ gint _foo_tree_data_list_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data); GList * _foo_tree_data_list_header_new (gint n_columns, GType *types); void _foo_tree_data_list_header_free (GList *header_list); GtkTreeDataSortHeader *_foo_tree_data_list_get_header (GList *header_list, gint sort_column_id); GList *_foo_tree_data_list_set_header (GList *header_list, gint sort_column_id, GtkTreeIterCompareFunc func, gpointer data, GDestroyNotify destroy); #endif /* __GTK_TREE_DATA_LIST_H__ */ sysprof-1.2.0/binfile.h0000644000175000017500000000326312021176713011725 00000000000000/* MemProf -- memory profiler and leak detector * Copyright 1999, 2000, 2001, Red Hat, Inc. * Copyright 2002, Kristian Rietveld * * Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, Red Hat, Inc. * Copyright 2004, 2005, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef BIN_FILE_H #define BIN_FILE_H #include #include typedef struct bin_file_t bin_file_t; typedef struct bin_symbol_t bin_symbol_t; /* Binary File */ bin_file_t * bin_file_new (const char *filename); void bin_file_free (bin_file_t *bin_file); const bin_symbol_t *bin_file_lookup_symbol (bin_file_t *bin_file, gulong address); gboolean bin_file_check_inode (bin_file_t *bin_file, ino_t inode); const char * bin_symbol_get_name (bin_file_t *bin_file, const bin_symbol_t *symbol); gulong bin_symbol_get_address (bin_file_t *bin_file, const bin_symbol_t *symbol); #endif sysprof-1.2.0/unwind.h0000644000175000017500000000006512021176713011616 00000000000000#include void unwind (const guchar *data); sysprof-1.2.0/build-aux/0000755000175000017500000000000012022706430012106 500000000000000sysprof-1.2.0/build-aux/depcomp0000755000175000017500000004755612021176741013431 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2011-12-04.11; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010, # 2011 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add `dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mechanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test "$stat" = 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/ \1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/ / G p }' >> "$depfile" rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: sysprof-1.2.0/build-aux/missing0000755000175000017500000002415212021176741013436 00000000000000#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2012-01-06.13; # UTC # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, # 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case $1 in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' autom4te touch the output file, or create a stub one automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file yacc create \`y.tab.[ch]', if possible, from existing .[ch] Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and \`g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; esac # normalize program name to check for. program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). This is about non-GNU programs, so use $1 not # $program. case $1 in lex*|yacc*) # Not GNU programs, they don't have --version. ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case $program in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case $f in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te*) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison*|yacc*) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then eval LASTARG=\${$#} case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.h fi ;; esac fi if test ! -f y.tab.h; then echo >y.tab.h fi if test ! -f y.tab.c; then echo 'main() { return 0; }' >y.tab.c fi ;; lex*|flex*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then eval LASTARG=\${$#} case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if test ! -f lex.yy.c; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit $? fi ;; makeinfo*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n ' /^@setfilename/{ s/.* \([^ ]*\) *$/\1/ p q }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: sysprof-1.2.0/build-aux/compile0000755000175000017500000001533712021176741013422 00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-01-04.17; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free # Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l*) lib=${1#-l} found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes set x "$@" "$dir/$lib.dll.lib" break fi if test -f "$dir/$lib.lib"; then found=yes set x "$@" "$dir/$lib.lib" break fi done IFS=$save_IFS test "$found" != yes && set x "$@" "$lib.lib" shift ;; -L*) func_file_conv "${1#-L}" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: sysprof-1.2.0/build-aux/install-sh0000755000175000017500000003325612021176741014050 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-01-19.21; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for `test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for `test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for `test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writeable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: sysprof-1.2.0/COPYING0000644000175000017500000004311012021176713011172 00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. sysprof-1.2.0/elfparser.h0000644000175000017500000000465512021176713012306 00000000000000/* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2006, 2007, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include typedef struct ElfSym ElfSym; typedef struct ElfParser ElfParser; ElfParser * elf_parser_new_from_data (const guchar *data, gsize length); ElfParser * elf_parser_new (const char *filename, GError **err); void elf_parser_free (ElfParser *parser); const char * elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32); const gchar *elf_parser_get_build_id (ElfParser *parser); const guchar *elf_parser_get_eh_frame (ElfParser *parser); const guchar *elf_parser_get_debug_frame (ElfParser *parser); gulong elf_parser_get_text_offset (ElfParser *parser); /* Lookup a symbol in the file. * * The symbol returned is const, so don't free it. It is valid until * elf_parser_free() is called on the parser. * * The address should be given in "file coordinates". This means that * if the file is mapped at address m and offset o, then an address a * should be looked up as "a - (m - o)". (m - o) is where the start * of the file would have been mapped, so a - (m - o) is the position * in the file of a. */ const ElfSym *elf_parser_lookup_symbol (ElfParser *parser, gulong address); guint32 elf_parser_get_crc32 (ElfParser *parser); const char * elf_parser_get_sym_name (ElfParser *parser, const ElfSym *sym); gulong elf_parser_get_sym_address (ElfParser *parser, const ElfSym *sym); gboolean elf_parser_owns_symbol (ElfParser *parser, const ElfSym *sym); char * elf_demangle (const char *name); sysprof-1.2.0/Makefile.in0000644000175000017500000031412512022706423012211 00000000000000# Makefile.in generated by automake 1.11.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : bin_PROGRAMS = sysprof-cli$(EXEEXT) $(am__EXEEXT_1) @BUILD_GUI_TRUE@am__append_1 = sysprof noinst_PROGRAMS = testelf$(EXEEXT) testunwind$(EXEEXT) \ testdemangle$(EXEEXT) subdir = . DIST_COMMON = README $(am__configure_deps) $(dist_pixmaps_DATA) \ $(dist_pkgdata_DATA) $(dist_udev_DATA) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ TODO build-aux/compile build-aux/depcomp build-aux/install-sh \ build-aux/missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @BUILD_GUI_TRUE@am__EXEEXT_1 = sysprof$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pixmapsdir)" \ "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(udevdir)" PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am__sysprof_SOURCES_DIST = binfile.h binfile.c collector.c collector.h \ demangle.c elfparser.c elfparser.h profile.h profile.c sfile.h \ sfile.c sformat.h sformat.c stackstash.h stackstash.c \ tracker.h tracker.c unwind.h unwind.c watch.h watch.c util.h \ footreestore.c footreestore.h footreedatalist.h \ footreedatalist.c treeviewutils.h treeviewutils.c sysprof.c am__objects_1 = sysprof-binfile.$(OBJEXT) sysprof-collector.$(OBJEXT) \ sysprof-demangle.$(OBJEXT) sysprof-elfparser.$(OBJEXT) \ sysprof-profile.$(OBJEXT) sysprof-sfile.$(OBJEXT) \ sysprof-sformat.$(OBJEXT) sysprof-stackstash.$(OBJEXT) \ sysprof-tracker.$(OBJEXT) sysprof-unwind.$(OBJEXT) \ sysprof-watch.$(OBJEXT) @BUILD_GUI_TRUE@am_sysprof_OBJECTS = $(am__objects_1) \ @BUILD_GUI_TRUE@ sysprof-footreestore.$(OBJEXT) \ @BUILD_GUI_TRUE@ sysprof-footreedatalist.$(OBJEXT) \ @BUILD_GUI_TRUE@ sysprof-treeviewutils.$(OBJEXT) \ @BUILD_GUI_TRUE@ sysprof-sysprof.$(OBJEXT) sysprof_OBJECTS = $(am_sysprof_OBJECTS) am__DEPENDENCIES_1 = @BUILD_GUI_TRUE@sysprof_DEPENDENCIES = $(am__DEPENDENCIES_1) am__objects_2 = sysprof_cli-binfile.$(OBJEXT) \ sysprof_cli-collector.$(OBJEXT) sysprof_cli-demangle.$(OBJEXT) \ sysprof_cli-elfparser.$(OBJEXT) sysprof_cli-profile.$(OBJEXT) \ sysprof_cli-sfile.$(OBJEXT) sysprof_cli-sformat.$(OBJEXT) \ sysprof_cli-stackstash.$(OBJEXT) sysprof_cli-tracker.$(OBJEXT) \ sysprof_cli-unwind.$(OBJEXT) sysprof_cli-watch.$(OBJEXT) am_sysprof_cli_OBJECTS = $(am__objects_2) \ sysprof_cli-signal-handler.$(OBJEXT) \ sysprof_cli-sysprof-cli.$(OBJEXT) sysprof_cli_OBJECTS = $(am_sysprof_cli_OBJECTS) sysprof_cli_DEPENDENCIES = $(am__DEPENDENCIES_1) am_testdemangle_OBJECTS = testdemangle-testdemangle.$(OBJEXT) \ testdemangle-elfparser.$(OBJEXT) \ testdemangle-demangle.$(OBJEXT) testdemangle_OBJECTS = $(am_testdemangle_OBJECTS) testdemangle_DEPENDENCIES = $(am__DEPENDENCIES_1) am_testelf_OBJECTS = testelf-testelf.$(OBJEXT) \ testelf-demangle.$(OBJEXT) testelf-elfparser.$(OBJEXT) testelf_OBJECTS = $(am_testelf_OBJECTS) testelf_DEPENDENCIES = $(am__DEPENDENCIES_1) am_testunwind_OBJECTS = testunwind-testunwind.$(OBJEXT) \ testunwind-demangle.$(OBJEXT) testunwind-elfparser.$(OBJEXT) \ testunwind-unwind.$(OBJEXT) testunwind_OBJECTS = $(am_testunwind_OBJECTS) testunwind_DEPENDENCIES = $(am__DEPENDENCIES_1) DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__depfiles_maybe = depfiles am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(sysprof_SOURCES) $(sysprof_cli_SOURCES) \ $(testdemangle_SOURCES) $(testelf_SOURCES) \ $(testunwind_SOURCES) DIST_SOURCES = $(am__sysprof_SOURCES_DIST) $(sysprof_cli_SOURCES) \ $(testdemangle_SOURCES) $(testelf_SOURCES) \ $(testunwind_SOURCES) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } DATA = $(dist_pixmaps_DATA) $(dist_pkgdata_DATA) $(dist_udev_DATA) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_DEP_CFLAGS = @CORE_DEP_CFLAGS@ CORE_DEP_LIBS = @CORE_DEP_LIBS@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EXEEXT = @EXEEXT@ GUI_DEP_CFLAGS = @GUI_DEP_CFLAGS@ GUI_DEP_LIBS = @GUI_DEP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MODULE_SUBDIR = @MODULE_SUBDIR@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} SYSPROF_CORE = \ binfile.h \ binfile.c \ collector.c \ collector.h \ demangle.c \ elfparser.c \ elfparser.h \ profile.h \ profile.c \ sfile.h \ sfile.c \ sformat.h \ sformat.c \ stackstash.h \ stackstash.c \ tracker.h \ tracker.c \ unwind.h \ unwind.c \ watch.h \ watch.c \ \ util.h # module/sysprof-module.h # # GUI version # @BUILD_GUI_TRUE@sysprof_SOURCES = \ @BUILD_GUI_TRUE@ $(SYSPROF_CORE) \ @BUILD_GUI_TRUE@ footreestore.c \ @BUILD_GUI_TRUE@ footreestore.h \ @BUILD_GUI_TRUE@ footreedatalist.h \ @BUILD_GUI_TRUE@ footreedatalist.c \ @BUILD_GUI_TRUE@ treeviewutils.h \ @BUILD_GUI_TRUE@ treeviewutils.c \ @BUILD_GUI_TRUE@ sysprof.c @BUILD_GUI_TRUE@sysprof_CPPFLAGS = \ @BUILD_GUI_TRUE@ $(GUI_DEP_CFLAGS) \ @BUILD_GUI_TRUE@ -DDATADIR=\"$(pkgdatadir)\" \ @BUILD_GUI_TRUE@ -DPIXMAPDIR=\"$(pixmapsdir)\" @BUILD_GUI_TRUE@sysprof_LDADD = $(GUI_DEP_LIBS) udevdir = $(sysconfdir)/udev/rules.d dist_udev_DATA = 60-sysprof.rules pixmapsdir = $(datadir)/pixmaps dist_pkgdata_DATA = sysprof.glade dist_pixmaps_DATA = sysprof-icon-16.png sysprof-icon-24.png sysprof-icon-32.png sysprof-icon-48.png # # Command line version # sysprof_cli_SOURCES = \ $(SYSPROF_CORE) \ signal-handler.h \ signal-handler.c \ sysprof-cli.c sysprof_cli_CPPFLAGS = \ $(CORE_DEP_CFLAGS) sysprof_cli_LDADD = $(CORE_DEP_LIBS) # testunwind testunwind_SOURCES = \ testunwind.c \ demangle.c \ elfparser.c \ elfparser.h \ unwind.c \ unwind.h testunwind_CPPFLAGS = $(CORE_DEP_CFLAGS) testunwind_LDADD = $(CORE_DEP_LIBS) # testelf testelf_SOURCES = \ testelf.c \ demangle.c \ elfparser.c \ elfparser.h testelf_CPPFLAGS = $(CORE_DEP_CFLAGS) testelf_LDADD = $(CORE_DEP_LIBS) # testdemangle testdemangle_SOURCES = \ testdemangle.c \ elfparser.c \ elfparser.h \ demangle.c testdemangle_CPPFLAGS = $(CORE_DEP_CFLAGS) testdemangle_LDADD = $(CORE_DEP_LIBS) all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .o .obj am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @if test ! -f $@; then rm -f stamp-h1; else :; fi @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) sysprof$(EXEEXT): $(sysprof_OBJECTS) $(sysprof_DEPENDENCIES) $(EXTRA_sysprof_DEPENDENCIES) @rm -f sysprof$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sysprof_OBJECTS) $(sysprof_LDADD) $(LIBS) sysprof-cli$(EXEEXT): $(sysprof_cli_OBJECTS) $(sysprof_cli_DEPENDENCIES) $(EXTRA_sysprof_cli_DEPENDENCIES) @rm -f sysprof-cli$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sysprof_cli_OBJECTS) $(sysprof_cli_LDADD) $(LIBS) testdemangle$(EXEEXT): $(testdemangle_OBJECTS) $(testdemangle_DEPENDENCIES) $(EXTRA_testdemangle_DEPENDENCIES) @rm -f testdemangle$(EXEEXT) $(AM_V_CCLD)$(LINK) $(testdemangle_OBJECTS) $(testdemangle_LDADD) $(LIBS) testelf$(EXEEXT): $(testelf_OBJECTS) $(testelf_DEPENDENCIES) $(EXTRA_testelf_DEPENDENCIES) @rm -f testelf$(EXEEXT) $(AM_V_CCLD)$(LINK) $(testelf_OBJECTS) $(testelf_LDADD) $(LIBS) testunwind$(EXEEXT): $(testunwind_OBJECTS) $(testunwind_DEPENDENCIES) $(EXTRA_testunwind_DEPENDENCIES) @rm -f testunwind$(EXEEXT) $(AM_V_CCLD)$(LINK) $(testunwind_OBJECTS) $(testunwind_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-binfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-collector.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-demangle.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-elfparser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-footreedatalist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-footreestore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-profile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-sfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-sformat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-stackstash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-sysprof.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-tracker.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-treeviewutils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-unwind.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof-watch.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof_cli-binfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof_cli-collector.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof_cli-demangle.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof_cli-elfparser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof_cli-profile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof_cli-sfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof_cli-sformat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof_cli-signal-handler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof_cli-stackstash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof_cli-sysprof-cli.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof_cli-tracker.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof_cli-unwind.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysprof_cli-watch.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testdemangle-demangle.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testdemangle-elfparser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testdemangle-testdemangle.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testelf-demangle.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testelf-elfparser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testelf-testelf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testunwind-demangle.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testunwind-elfparser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testunwind-testunwind.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testunwind-unwind.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` sysprof-binfile.o: binfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-binfile.o -MD -MP -MF $(DEPDIR)/sysprof-binfile.Tpo -c -o sysprof-binfile.o `test -f 'binfile.c' || echo '$(srcdir)/'`binfile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-binfile.Tpo $(DEPDIR)/sysprof-binfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='binfile.c' object='sysprof-binfile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-binfile.o `test -f 'binfile.c' || echo '$(srcdir)/'`binfile.c sysprof-binfile.obj: binfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-binfile.obj -MD -MP -MF $(DEPDIR)/sysprof-binfile.Tpo -c -o sysprof-binfile.obj `if test -f 'binfile.c'; then $(CYGPATH_W) 'binfile.c'; else $(CYGPATH_W) '$(srcdir)/binfile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-binfile.Tpo $(DEPDIR)/sysprof-binfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='binfile.c' object='sysprof-binfile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-binfile.obj `if test -f 'binfile.c'; then $(CYGPATH_W) 'binfile.c'; else $(CYGPATH_W) '$(srcdir)/binfile.c'; fi` sysprof-collector.o: collector.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-collector.o -MD -MP -MF $(DEPDIR)/sysprof-collector.Tpo -c -o sysprof-collector.o `test -f 'collector.c' || echo '$(srcdir)/'`collector.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-collector.Tpo $(DEPDIR)/sysprof-collector.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='collector.c' object='sysprof-collector.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-collector.o `test -f 'collector.c' || echo '$(srcdir)/'`collector.c sysprof-collector.obj: collector.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-collector.obj -MD -MP -MF $(DEPDIR)/sysprof-collector.Tpo -c -o sysprof-collector.obj `if test -f 'collector.c'; then $(CYGPATH_W) 'collector.c'; else $(CYGPATH_W) '$(srcdir)/collector.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-collector.Tpo $(DEPDIR)/sysprof-collector.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='collector.c' object='sysprof-collector.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-collector.obj `if test -f 'collector.c'; then $(CYGPATH_W) 'collector.c'; else $(CYGPATH_W) '$(srcdir)/collector.c'; fi` sysprof-demangle.o: demangle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-demangle.o -MD -MP -MF $(DEPDIR)/sysprof-demangle.Tpo -c -o sysprof-demangle.o `test -f 'demangle.c' || echo '$(srcdir)/'`demangle.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-demangle.Tpo $(DEPDIR)/sysprof-demangle.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='demangle.c' object='sysprof-demangle.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-demangle.o `test -f 'demangle.c' || echo '$(srcdir)/'`demangle.c sysprof-demangle.obj: demangle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-demangle.obj -MD -MP -MF $(DEPDIR)/sysprof-demangle.Tpo -c -o sysprof-demangle.obj `if test -f 'demangle.c'; then $(CYGPATH_W) 'demangle.c'; else $(CYGPATH_W) '$(srcdir)/demangle.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-demangle.Tpo $(DEPDIR)/sysprof-demangle.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='demangle.c' object='sysprof-demangle.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-demangle.obj `if test -f 'demangle.c'; then $(CYGPATH_W) 'demangle.c'; else $(CYGPATH_W) '$(srcdir)/demangle.c'; fi` sysprof-elfparser.o: elfparser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-elfparser.o -MD -MP -MF $(DEPDIR)/sysprof-elfparser.Tpo -c -o sysprof-elfparser.o `test -f 'elfparser.c' || echo '$(srcdir)/'`elfparser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-elfparser.Tpo $(DEPDIR)/sysprof-elfparser.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elfparser.c' object='sysprof-elfparser.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-elfparser.o `test -f 'elfparser.c' || echo '$(srcdir)/'`elfparser.c sysprof-elfparser.obj: elfparser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-elfparser.obj -MD -MP -MF $(DEPDIR)/sysprof-elfparser.Tpo -c -o sysprof-elfparser.obj `if test -f 'elfparser.c'; then $(CYGPATH_W) 'elfparser.c'; else $(CYGPATH_W) '$(srcdir)/elfparser.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-elfparser.Tpo $(DEPDIR)/sysprof-elfparser.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elfparser.c' object='sysprof-elfparser.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-elfparser.obj `if test -f 'elfparser.c'; then $(CYGPATH_W) 'elfparser.c'; else $(CYGPATH_W) '$(srcdir)/elfparser.c'; fi` sysprof-profile.o: profile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-profile.o -MD -MP -MF $(DEPDIR)/sysprof-profile.Tpo -c -o sysprof-profile.o `test -f 'profile.c' || echo '$(srcdir)/'`profile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-profile.Tpo $(DEPDIR)/sysprof-profile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='profile.c' object='sysprof-profile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-profile.o `test -f 'profile.c' || echo '$(srcdir)/'`profile.c sysprof-profile.obj: profile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-profile.obj -MD -MP -MF $(DEPDIR)/sysprof-profile.Tpo -c -o sysprof-profile.obj `if test -f 'profile.c'; then $(CYGPATH_W) 'profile.c'; else $(CYGPATH_W) '$(srcdir)/profile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-profile.Tpo $(DEPDIR)/sysprof-profile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='profile.c' object='sysprof-profile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-profile.obj `if test -f 'profile.c'; then $(CYGPATH_W) 'profile.c'; else $(CYGPATH_W) '$(srcdir)/profile.c'; fi` sysprof-sfile.o: sfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-sfile.o -MD -MP -MF $(DEPDIR)/sysprof-sfile.Tpo -c -o sysprof-sfile.o `test -f 'sfile.c' || echo '$(srcdir)/'`sfile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-sfile.Tpo $(DEPDIR)/sysprof-sfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sfile.c' object='sysprof-sfile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-sfile.o `test -f 'sfile.c' || echo '$(srcdir)/'`sfile.c sysprof-sfile.obj: sfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-sfile.obj -MD -MP -MF $(DEPDIR)/sysprof-sfile.Tpo -c -o sysprof-sfile.obj `if test -f 'sfile.c'; then $(CYGPATH_W) 'sfile.c'; else $(CYGPATH_W) '$(srcdir)/sfile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-sfile.Tpo $(DEPDIR)/sysprof-sfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sfile.c' object='sysprof-sfile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-sfile.obj `if test -f 'sfile.c'; then $(CYGPATH_W) 'sfile.c'; else $(CYGPATH_W) '$(srcdir)/sfile.c'; fi` sysprof-sformat.o: sformat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-sformat.o -MD -MP -MF $(DEPDIR)/sysprof-sformat.Tpo -c -o sysprof-sformat.o `test -f 'sformat.c' || echo '$(srcdir)/'`sformat.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-sformat.Tpo $(DEPDIR)/sysprof-sformat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sformat.c' object='sysprof-sformat.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-sformat.o `test -f 'sformat.c' || echo '$(srcdir)/'`sformat.c sysprof-sformat.obj: sformat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-sformat.obj -MD -MP -MF $(DEPDIR)/sysprof-sformat.Tpo -c -o sysprof-sformat.obj `if test -f 'sformat.c'; then $(CYGPATH_W) 'sformat.c'; else $(CYGPATH_W) '$(srcdir)/sformat.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-sformat.Tpo $(DEPDIR)/sysprof-sformat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sformat.c' object='sysprof-sformat.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-sformat.obj `if test -f 'sformat.c'; then $(CYGPATH_W) 'sformat.c'; else $(CYGPATH_W) '$(srcdir)/sformat.c'; fi` sysprof-stackstash.o: stackstash.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-stackstash.o -MD -MP -MF $(DEPDIR)/sysprof-stackstash.Tpo -c -o sysprof-stackstash.o `test -f 'stackstash.c' || echo '$(srcdir)/'`stackstash.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-stackstash.Tpo $(DEPDIR)/sysprof-stackstash.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stackstash.c' object='sysprof-stackstash.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-stackstash.o `test -f 'stackstash.c' || echo '$(srcdir)/'`stackstash.c sysprof-stackstash.obj: stackstash.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-stackstash.obj -MD -MP -MF $(DEPDIR)/sysprof-stackstash.Tpo -c -o sysprof-stackstash.obj `if test -f 'stackstash.c'; then $(CYGPATH_W) 'stackstash.c'; else $(CYGPATH_W) '$(srcdir)/stackstash.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-stackstash.Tpo $(DEPDIR)/sysprof-stackstash.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stackstash.c' object='sysprof-stackstash.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-stackstash.obj `if test -f 'stackstash.c'; then $(CYGPATH_W) 'stackstash.c'; else $(CYGPATH_W) '$(srcdir)/stackstash.c'; fi` sysprof-tracker.o: tracker.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-tracker.o -MD -MP -MF $(DEPDIR)/sysprof-tracker.Tpo -c -o sysprof-tracker.o `test -f 'tracker.c' || echo '$(srcdir)/'`tracker.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-tracker.Tpo $(DEPDIR)/sysprof-tracker.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tracker.c' object='sysprof-tracker.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-tracker.o `test -f 'tracker.c' || echo '$(srcdir)/'`tracker.c sysprof-tracker.obj: tracker.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-tracker.obj -MD -MP -MF $(DEPDIR)/sysprof-tracker.Tpo -c -o sysprof-tracker.obj `if test -f 'tracker.c'; then $(CYGPATH_W) 'tracker.c'; else $(CYGPATH_W) '$(srcdir)/tracker.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-tracker.Tpo $(DEPDIR)/sysprof-tracker.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tracker.c' object='sysprof-tracker.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-tracker.obj `if test -f 'tracker.c'; then $(CYGPATH_W) 'tracker.c'; else $(CYGPATH_W) '$(srcdir)/tracker.c'; fi` sysprof-unwind.o: unwind.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-unwind.o -MD -MP -MF $(DEPDIR)/sysprof-unwind.Tpo -c -o sysprof-unwind.o `test -f 'unwind.c' || echo '$(srcdir)/'`unwind.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-unwind.Tpo $(DEPDIR)/sysprof-unwind.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind.c' object='sysprof-unwind.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-unwind.o `test -f 'unwind.c' || echo '$(srcdir)/'`unwind.c sysprof-unwind.obj: unwind.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-unwind.obj -MD -MP -MF $(DEPDIR)/sysprof-unwind.Tpo -c -o sysprof-unwind.obj `if test -f 'unwind.c'; then $(CYGPATH_W) 'unwind.c'; else $(CYGPATH_W) '$(srcdir)/unwind.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-unwind.Tpo $(DEPDIR)/sysprof-unwind.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind.c' object='sysprof-unwind.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-unwind.obj `if test -f 'unwind.c'; then $(CYGPATH_W) 'unwind.c'; else $(CYGPATH_W) '$(srcdir)/unwind.c'; fi` sysprof-watch.o: watch.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-watch.o -MD -MP -MF $(DEPDIR)/sysprof-watch.Tpo -c -o sysprof-watch.o `test -f 'watch.c' || echo '$(srcdir)/'`watch.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-watch.Tpo $(DEPDIR)/sysprof-watch.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='watch.c' object='sysprof-watch.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-watch.o `test -f 'watch.c' || echo '$(srcdir)/'`watch.c sysprof-watch.obj: watch.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-watch.obj -MD -MP -MF $(DEPDIR)/sysprof-watch.Tpo -c -o sysprof-watch.obj `if test -f 'watch.c'; then $(CYGPATH_W) 'watch.c'; else $(CYGPATH_W) '$(srcdir)/watch.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-watch.Tpo $(DEPDIR)/sysprof-watch.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='watch.c' object='sysprof-watch.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-watch.obj `if test -f 'watch.c'; then $(CYGPATH_W) 'watch.c'; else $(CYGPATH_W) '$(srcdir)/watch.c'; fi` sysprof-footreestore.o: footreestore.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-footreestore.o -MD -MP -MF $(DEPDIR)/sysprof-footreestore.Tpo -c -o sysprof-footreestore.o `test -f 'footreestore.c' || echo '$(srcdir)/'`footreestore.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-footreestore.Tpo $(DEPDIR)/sysprof-footreestore.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='footreestore.c' object='sysprof-footreestore.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-footreestore.o `test -f 'footreestore.c' || echo '$(srcdir)/'`footreestore.c sysprof-footreestore.obj: footreestore.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-footreestore.obj -MD -MP -MF $(DEPDIR)/sysprof-footreestore.Tpo -c -o sysprof-footreestore.obj `if test -f 'footreestore.c'; then $(CYGPATH_W) 'footreestore.c'; else $(CYGPATH_W) '$(srcdir)/footreestore.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-footreestore.Tpo $(DEPDIR)/sysprof-footreestore.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='footreestore.c' object='sysprof-footreestore.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-footreestore.obj `if test -f 'footreestore.c'; then $(CYGPATH_W) 'footreestore.c'; else $(CYGPATH_W) '$(srcdir)/footreestore.c'; fi` sysprof-footreedatalist.o: footreedatalist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-footreedatalist.o -MD -MP -MF $(DEPDIR)/sysprof-footreedatalist.Tpo -c -o sysprof-footreedatalist.o `test -f 'footreedatalist.c' || echo '$(srcdir)/'`footreedatalist.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-footreedatalist.Tpo $(DEPDIR)/sysprof-footreedatalist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='footreedatalist.c' object='sysprof-footreedatalist.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-footreedatalist.o `test -f 'footreedatalist.c' || echo '$(srcdir)/'`footreedatalist.c sysprof-footreedatalist.obj: footreedatalist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-footreedatalist.obj -MD -MP -MF $(DEPDIR)/sysprof-footreedatalist.Tpo -c -o sysprof-footreedatalist.obj `if test -f 'footreedatalist.c'; then $(CYGPATH_W) 'footreedatalist.c'; else $(CYGPATH_W) '$(srcdir)/footreedatalist.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-footreedatalist.Tpo $(DEPDIR)/sysprof-footreedatalist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='footreedatalist.c' object='sysprof-footreedatalist.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-footreedatalist.obj `if test -f 'footreedatalist.c'; then $(CYGPATH_W) 'footreedatalist.c'; else $(CYGPATH_W) '$(srcdir)/footreedatalist.c'; fi` sysprof-treeviewutils.o: treeviewutils.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-treeviewutils.o -MD -MP -MF $(DEPDIR)/sysprof-treeviewutils.Tpo -c -o sysprof-treeviewutils.o `test -f 'treeviewutils.c' || echo '$(srcdir)/'`treeviewutils.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-treeviewutils.Tpo $(DEPDIR)/sysprof-treeviewutils.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='treeviewutils.c' object='sysprof-treeviewutils.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-treeviewutils.o `test -f 'treeviewutils.c' || echo '$(srcdir)/'`treeviewutils.c sysprof-treeviewutils.obj: treeviewutils.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-treeviewutils.obj -MD -MP -MF $(DEPDIR)/sysprof-treeviewutils.Tpo -c -o sysprof-treeviewutils.obj `if test -f 'treeviewutils.c'; then $(CYGPATH_W) 'treeviewutils.c'; else $(CYGPATH_W) '$(srcdir)/treeviewutils.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-treeviewutils.Tpo $(DEPDIR)/sysprof-treeviewutils.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='treeviewutils.c' object='sysprof-treeviewutils.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-treeviewutils.obj `if test -f 'treeviewutils.c'; then $(CYGPATH_W) 'treeviewutils.c'; else $(CYGPATH_W) '$(srcdir)/treeviewutils.c'; fi` sysprof-sysprof.o: sysprof.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-sysprof.o -MD -MP -MF $(DEPDIR)/sysprof-sysprof.Tpo -c -o sysprof-sysprof.o `test -f 'sysprof.c' || echo '$(srcdir)/'`sysprof.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-sysprof.Tpo $(DEPDIR)/sysprof-sysprof.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sysprof.c' object='sysprof-sysprof.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-sysprof.o `test -f 'sysprof.c' || echo '$(srcdir)/'`sysprof.c sysprof-sysprof.obj: sysprof.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof-sysprof.obj -MD -MP -MF $(DEPDIR)/sysprof-sysprof.Tpo -c -o sysprof-sysprof.obj `if test -f 'sysprof.c'; then $(CYGPATH_W) 'sysprof.c'; else $(CYGPATH_W) '$(srcdir)/sysprof.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof-sysprof.Tpo $(DEPDIR)/sysprof-sysprof.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sysprof.c' object='sysprof-sysprof.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof-sysprof.obj `if test -f 'sysprof.c'; then $(CYGPATH_W) 'sysprof.c'; else $(CYGPATH_W) '$(srcdir)/sysprof.c'; fi` sysprof_cli-binfile.o: binfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-binfile.o -MD -MP -MF $(DEPDIR)/sysprof_cli-binfile.Tpo -c -o sysprof_cli-binfile.o `test -f 'binfile.c' || echo '$(srcdir)/'`binfile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-binfile.Tpo $(DEPDIR)/sysprof_cli-binfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='binfile.c' object='sysprof_cli-binfile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-binfile.o `test -f 'binfile.c' || echo '$(srcdir)/'`binfile.c sysprof_cli-binfile.obj: binfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-binfile.obj -MD -MP -MF $(DEPDIR)/sysprof_cli-binfile.Tpo -c -o sysprof_cli-binfile.obj `if test -f 'binfile.c'; then $(CYGPATH_W) 'binfile.c'; else $(CYGPATH_W) '$(srcdir)/binfile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-binfile.Tpo $(DEPDIR)/sysprof_cli-binfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='binfile.c' object='sysprof_cli-binfile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-binfile.obj `if test -f 'binfile.c'; then $(CYGPATH_W) 'binfile.c'; else $(CYGPATH_W) '$(srcdir)/binfile.c'; fi` sysprof_cli-collector.o: collector.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-collector.o -MD -MP -MF $(DEPDIR)/sysprof_cli-collector.Tpo -c -o sysprof_cli-collector.o `test -f 'collector.c' || echo '$(srcdir)/'`collector.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-collector.Tpo $(DEPDIR)/sysprof_cli-collector.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='collector.c' object='sysprof_cli-collector.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-collector.o `test -f 'collector.c' || echo '$(srcdir)/'`collector.c sysprof_cli-collector.obj: collector.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-collector.obj -MD -MP -MF $(DEPDIR)/sysprof_cli-collector.Tpo -c -o sysprof_cli-collector.obj `if test -f 'collector.c'; then $(CYGPATH_W) 'collector.c'; else $(CYGPATH_W) '$(srcdir)/collector.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-collector.Tpo $(DEPDIR)/sysprof_cli-collector.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='collector.c' object='sysprof_cli-collector.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-collector.obj `if test -f 'collector.c'; then $(CYGPATH_W) 'collector.c'; else $(CYGPATH_W) '$(srcdir)/collector.c'; fi` sysprof_cli-demangle.o: demangle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-demangle.o -MD -MP -MF $(DEPDIR)/sysprof_cli-demangle.Tpo -c -o sysprof_cli-demangle.o `test -f 'demangle.c' || echo '$(srcdir)/'`demangle.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-demangle.Tpo $(DEPDIR)/sysprof_cli-demangle.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='demangle.c' object='sysprof_cli-demangle.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-demangle.o `test -f 'demangle.c' || echo '$(srcdir)/'`demangle.c sysprof_cli-demangle.obj: demangle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-demangle.obj -MD -MP -MF $(DEPDIR)/sysprof_cli-demangle.Tpo -c -o sysprof_cli-demangle.obj `if test -f 'demangle.c'; then $(CYGPATH_W) 'demangle.c'; else $(CYGPATH_W) '$(srcdir)/demangle.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-demangle.Tpo $(DEPDIR)/sysprof_cli-demangle.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='demangle.c' object='sysprof_cli-demangle.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-demangle.obj `if test -f 'demangle.c'; then $(CYGPATH_W) 'demangle.c'; else $(CYGPATH_W) '$(srcdir)/demangle.c'; fi` sysprof_cli-elfparser.o: elfparser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-elfparser.o -MD -MP -MF $(DEPDIR)/sysprof_cli-elfparser.Tpo -c -o sysprof_cli-elfparser.o `test -f 'elfparser.c' || echo '$(srcdir)/'`elfparser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-elfparser.Tpo $(DEPDIR)/sysprof_cli-elfparser.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elfparser.c' object='sysprof_cli-elfparser.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-elfparser.o `test -f 'elfparser.c' || echo '$(srcdir)/'`elfparser.c sysprof_cli-elfparser.obj: elfparser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-elfparser.obj -MD -MP -MF $(DEPDIR)/sysprof_cli-elfparser.Tpo -c -o sysprof_cli-elfparser.obj `if test -f 'elfparser.c'; then $(CYGPATH_W) 'elfparser.c'; else $(CYGPATH_W) '$(srcdir)/elfparser.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-elfparser.Tpo $(DEPDIR)/sysprof_cli-elfparser.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elfparser.c' object='sysprof_cli-elfparser.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-elfparser.obj `if test -f 'elfparser.c'; then $(CYGPATH_W) 'elfparser.c'; else $(CYGPATH_W) '$(srcdir)/elfparser.c'; fi` sysprof_cli-profile.o: profile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-profile.o -MD -MP -MF $(DEPDIR)/sysprof_cli-profile.Tpo -c -o sysprof_cli-profile.o `test -f 'profile.c' || echo '$(srcdir)/'`profile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-profile.Tpo $(DEPDIR)/sysprof_cli-profile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='profile.c' object='sysprof_cli-profile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-profile.o `test -f 'profile.c' || echo '$(srcdir)/'`profile.c sysprof_cli-profile.obj: profile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-profile.obj -MD -MP -MF $(DEPDIR)/sysprof_cli-profile.Tpo -c -o sysprof_cli-profile.obj `if test -f 'profile.c'; then $(CYGPATH_W) 'profile.c'; else $(CYGPATH_W) '$(srcdir)/profile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-profile.Tpo $(DEPDIR)/sysprof_cli-profile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='profile.c' object='sysprof_cli-profile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-profile.obj `if test -f 'profile.c'; then $(CYGPATH_W) 'profile.c'; else $(CYGPATH_W) '$(srcdir)/profile.c'; fi` sysprof_cli-sfile.o: sfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-sfile.o -MD -MP -MF $(DEPDIR)/sysprof_cli-sfile.Tpo -c -o sysprof_cli-sfile.o `test -f 'sfile.c' || echo '$(srcdir)/'`sfile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-sfile.Tpo $(DEPDIR)/sysprof_cli-sfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sfile.c' object='sysprof_cli-sfile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-sfile.o `test -f 'sfile.c' || echo '$(srcdir)/'`sfile.c sysprof_cli-sfile.obj: sfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-sfile.obj -MD -MP -MF $(DEPDIR)/sysprof_cli-sfile.Tpo -c -o sysprof_cli-sfile.obj `if test -f 'sfile.c'; then $(CYGPATH_W) 'sfile.c'; else $(CYGPATH_W) '$(srcdir)/sfile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-sfile.Tpo $(DEPDIR)/sysprof_cli-sfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sfile.c' object='sysprof_cli-sfile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-sfile.obj `if test -f 'sfile.c'; then $(CYGPATH_W) 'sfile.c'; else $(CYGPATH_W) '$(srcdir)/sfile.c'; fi` sysprof_cli-sformat.o: sformat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-sformat.o -MD -MP -MF $(DEPDIR)/sysprof_cli-sformat.Tpo -c -o sysprof_cli-sformat.o `test -f 'sformat.c' || echo '$(srcdir)/'`sformat.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-sformat.Tpo $(DEPDIR)/sysprof_cli-sformat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sformat.c' object='sysprof_cli-sformat.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-sformat.o `test -f 'sformat.c' || echo '$(srcdir)/'`sformat.c sysprof_cli-sformat.obj: sformat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-sformat.obj -MD -MP -MF $(DEPDIR)/sysprof_cli-sformat.Tpo -c -o sysprof_cli-sformat.obj `if test -f 'sformat.c'; then $(CYGPATH_W) 'sformat.c'; else $(CYGPATH_W) '$(srcdir)/sformat.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-sformat.Tpo $(DEPDIR)/sysprof_cli-sformat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sformat.c' object='sysprof_cli-sformat.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-sformat.obj `if test -f 'sformat.c'; then $(CYGPATH_W) 'sformat.c'; else $(CYGPATH_W) '$(srcdir)/sformat.c'; fi` sysprof_cli-stackstash.o: stackstash.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-stackstash.o -MD -MP -MF $(DEPDIR)/sysprof_cli-stackstash.Tpo -c -o sysprof_cli-stackstash.o `test -f 'stackstash.c' || echo '$(srcdir)/'`stackstash.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-stackstash.Tpo $(DEPDIR)/sysprof_cli-stackstash.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stackstash.c' object='sysprof_cli-stackstash.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-stackstash.o `test -f 'stackstash.c' || echo '$(srcdir)/'`stackstash.c sysprof_cli-stackstash.obj: stackstash.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-stackstash.obj -MD -MP -MF $(DEPDIR)/sysprof_cli-stackstash.Tpo -c -o sysprof_cli-stackstash.obj `if test -f 'stackstash.c'; then $(CYGPATH_W) 'stackstash.c'; else $(CYGPATH_W) '$(srcdir)/stackstash.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-stackstash.Tpo $(DEPDIR)/sysprof_cli-stackstash.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stackstash.c' object='sysprof_cli-stackstash.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-stackstash.obj `if test -f 'stackstash.c'; then $(CYGPATH_W) 'stackstash.c'; else $(CYGPATH_W) '$(srcdir)/stackstash.c'; fi` sysprof_cli-tracker.o: tracker.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-tracker.o -MD -MP -MF $(DEPDIR)/sysprof_cli-tracker.Tpo -c -o sysprof_cli-tracker.o `test -f 'tracker.c' || echo '$(srcdir)/'`tracker.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-tracker.Tpo $(DEPDIR)/sysprof_cli-tracker.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tracker.c' object='sysprof_cli-tracker.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-tracker.o `test -f 'tracker.c' || echo '$(srcdir)/'`tracker.c sysprof_cli-tracker.obj: tracker.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-tracker.obj -MD -MP -MF $(DEPDIR)/sysprof_cli-tracker.Tpo -c -o sysprof_cli-tracker.obj `if test -f 'tracker.c'; then $(CYGPATH_W) 'tracker.c'; else $(CYGPATH_W) '$(srcdir)/tracker.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-tracker.Tpo $(DEPDIR)/sysprof_cli-tracker.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tracker.c' object='sysprof_cli-tracker.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-tracker.obj `if test -f 'tracker.c'; then $(CYGPATH_W) 'tracker.c'; else $(CYGPATH_W) '$(srcdir)/tracker.c'; fi` sysprof_cli-unwind.o: unwind.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-unwind.o -MD -MP -MF $(DEPDIR)/sysprof_cli-unwind.Tpo -c -o sysprof_cli-unwind.o `test -f 'unwind.c' || echo '$(srcdir)/'`unwind.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-unwind.Tpo $(DEPDIR)/sysprof_cli-unwind.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind.c' object='sysprof_cli-unwind.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-unwind.o `test -f 'unwind.c' || echo '$(srcdir)/'`unwind.c sysprof_cli-unwind.obj: unwind.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-unwind.obj -MD -MP -MF $(DEPDIR)/sysprof_cli-unwind.Tpo -c -o sysprof_cli-unwind.obj `if test -f 'unwind.c'; then $(CYGPATH_W) 'unwind.c'; else $(CYGPATH_W) '$(srcdir)/unwind.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-unwind.Tpo $(DEPDIR)/sysprof_cli-unwind.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind.c' object='sysprof_cli-unwind.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-unwind.obj `if test -f 'unwind.c'; then $(CYGPATH_W) 'unwind.c'; else $(CYGPATH_W) '$(srcdir)/unwind.c'; fi` sysprof_cli-watch.o: watch.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-watch.o -MD -MP -MF $(DEPDIR)/sysprof_cli-watch.Tpo -c -o sysprof_cli-watch.o `test -f 'watch.c' || echo '$(srcdir)/'`watch.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-watch.Tpo $(DEPDIR)/sysprof_cli-watch.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='watch.c' object='sysprof_cli-watch.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-watch.o `test -f 'watch.c' || echo '$(srcdir)/'`watch.c sysprof_cli-watch.obj: watch.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-watch.obj -MD -MP -MF $(DEPDIR)/sysprof_cli-watch.Tpo -c -o sysprof_cli-watch.obj `if test -f 'watch.c'; then $(CYGPATH_W) 'watch.c'; else $(CYGPATH_W) '$(srcdir)/watch.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-watch.Tpo $(DEPDIR)/sysprof_cli-watch.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='watch.c' object='sysprof_cli-watch.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-watch.obj `if test -f 'watch.c'; then $(CYGPATH_W) 'watch.c'; else $(CYGPATH_W) '$(srcdir)/watch.c'; fi` sysprof_cli-signal-handler.o: signal-handler.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-signal-handler.o -MD -MP -MF $(DEPDIR)/sysprof_cli-signal-handler.Tpo -c -o sysprof_cli-signal-handler.o `test -f 'signal-handler.c' || echo '$(srcdir)/'`signal-handler.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-signal-handler.Tpo $(DEPDIR)/sysprof_cli-signal-handler.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='signal-handler.c' object='sysprof_cli-signal-handler.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-signal-handler.o `test -f 'signal-handler.c' || echo '$(srcdir)/'`signal-handler.c sysprof_cli-signal-handler.obj: signal-handler.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-signal-handler.obj -MD -MP -MF $(DEPDIR)/sysprof_cli-signal-handler.Tpo -c -o sysprof_cli-signal-handler.obj `if test -f 'signal-handler.c'; then $(CYGPATH_W) 'signal-handler.c'; else $(CYGPATH_W) '$(srcdir)/signal-handler.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-signal-handler.Tpo $(DEPDIR)/sysprof_cli-signal-handler.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='signal-handler.c' object='sysprof_cli-signal-handler.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-signal-handler.obj `if test -f 'signal-handler.c'; then $(CYGPATH_W) 'signal-handler.c'; else $(CYGPATH_W) '$(srcdir)/signal-handler.c'; fi` sysprof_cli-sysprof-cli.o: sysprof-cli.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-sysprof-cli.o -MD -MP -MF $(DEPDIR)/sysprof_cli-sysprof-cli.Tpo -c -o sysprof_cli-sysprof-cli.o `test -f 'sysprof-cli.c' || echo '$(srcdir)/'`sysprof-cli.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-sysprof-cli.Tpo $(DEPDIR)/sysprof_cli-sysprof-cli.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sysprof-cli.c' object='sysprof_cli-sysprof-cli.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-sysprof-cli.o `test -f 'sysprof-cli.c' || echo '$(srcdir)/'`sysprof-cli.c sysprof_cli-sysprof-cli.obj: sysprof-cli.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysprof_cli-sysprof-cli.obj -MD -MP -MF $(DEPDIR)/sysprof_cli-sysprof-cli.Tpo -c -o sysprof_cli-sysprof-cli.obj `if test -f 'sysprof-cli.c'; then $(CYGPATH_W) 'sysprof-cli.c'; else $(CYGPATH_W) '$(srcdir)/sysprof-cli.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sysprof_cli-sysprof-cli.Tpo $(DEPDIR)/sysprof_cli-sysprof-cli.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sysprof-cli.c' object='sysprof_cli-sysprof-cli.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sysprof_cli_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysprof_cli-sysprof-cli.obj `if test -f 'sysprof-cli.c'; then $(CYGPATH_W) 'sysprof-cli.c'; else $(CYGPATH_W) '$(srcdir)/sysprof-cli.c'; fi` testdemangle-testdemangle.o: testdemangle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testdemangle_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testdemangle-testdemangle.o -MD -MP -MF $(DEPDIR)/testdemangle-testdemangle.Tpo -c -o testdemangle-testdemangle.o `test -f 'testdemangle.c' || echo '$(srcdir)/'`testdemangle.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testdemangle-testdemangle.Tpo $(DEPDIR)/testdemangle-testdemangle.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testdemangle.c' object='testdemangle-testdemangle.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testdemangle_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testdemangle-testdemangle.o `test -f 'testdemangle.c' || echo '$(srcdir)/'`testdemangle.c testdemangle-testdemangle.obj: testdemangle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testdemangle_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testdemangle-testdemangle.obj -MD -MP -MF $(DEPDIR)/testdemangle-testdemangle.Tpo -c -o testdemangle-testdemangle.obj `if test -f 'testdemangle.c'; then $(CYGPATH_W) 'testdemangle.c'; else $(CYGPATH_W) '$(srcdir)/testdemangle.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testdemangle-testdemangle.Tpo $(DEPDIR)/testdemangle-testdemangle.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testdemangle.c' object='testdemangle-testdemangle.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testdemangle_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testdemangle-testdemangle.obj `if test -f 'testdemangle.c'; then $(CYGPATH_W) 'testdemangle.c'; else $(CYGPATH_W) '$(srcdir)/testdemangle.c'; fi` testdemangle-elfparser.o: elfparser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testdemangle_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testdemangle-elfparser.o -MD -MP -MF $(DEPDIR)/testdemangle-elfparser.Tpo -c -o testdemangle-elfparser.o `test -f 'elfparser.c' || echo '$(srcdir)/'`elfparser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testdemangle-elfparser.Tpo $(DEPDIR)/testdemangle-elfparser.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elfparser.c' object='testdemangle-elfparser.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testdemangle_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testdemangle-elfparser.o `test -f 'elfparser.c' || echo '$(srcdir)/'`elfparser.c testdemangle-elfparser.obj: elfparser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testdemangle_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testdemangle-elfparser.obj -MD -MP -MF $(DEPDIR)/testdemangle-elfparser.Tpo -c -o testdemangle-elfparser.obj `if test -f 'elfparser.c'; then $(CYGPATH_W) 'elfparser.c'; else $(CYGPATH_W) '$(srcdir)/elfparser.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testdemangle-elfparser.Tpo $(DEPDIR)/testdemangle-elfparser.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elfparser.c' object='testdemangle-elfparser.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testdemangle_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testdemangle-elfparser.obj `if test -f 'elfparser.c'; then $(CYGPATH_W) 'elfparser.c'; else $(CYGPATH_W) '$(srcdir)/elfparser.c'; fi` testdemangle-demangle.o: demangle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testdemangle_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testdemangle-demangle.o -MD -MP -MF $(DEPDIR)/testdemangle-demangle.Tpo -c -o testdemangle-demangle.o `test -f 'demangle.c' || echo '$(srcdir)/'`demangle.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testdemangle-demangle.Tpo $(DEPDIR)/testdemangle-demangle.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='demangle.c' object='testdemangle-demangle.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testdemangle_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testdemangle-demangle.o `test -f 'demangle.c' || echo '$(srcdir)/'`demangle.c testdemangle-demangle.obj: demangle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testdemangle_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testdemangle-demangle.obj -MD -MP -MF $(DEPDIR)/testdemangle-demangle.Tpo -c -o testdemangle-demangle.obj `if test -f 'demangle.c'; then $(CYGPATH_W) 'demangle.c'; else $(CYGPATH_W) '$(srcdir)/demangle.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testdemangle-demangle.Tpo $(DEPDIR)/testdemangle-demangle.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='demangle.c' object='testdemangle-demangle.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testdemangle_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testdemangle-demangle.obj `if test -f 'demangle.c'; then $(CYGPATH_W) 'demangle.c'; else $(CYGPATH_W) '$(srcdir)/demangle.c'; fi` testelf-testelf.o: testelf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testelf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testelf-testelf.o -MD -MP -MF $(DEPDIR)/testelf-testelf.Tpo -c -o testelf-testelf.o `test -f 'testelf.c' || echo '$(srcdir)/'`testelf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testelf-testelf.Tpo $(DEPDIR)/testelf-testelf.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testelf.c' object='testelf-testelf.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testelf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testelf-testelf.o `test -f 'testelf.c' || echo '$(srcdir)/'`testelf.c testelf-testelf.obj: testelf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testelf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testelf-testelf.obj -MD -MP -MF $(DEPDIR)/testelf-testelf.Tpo -c -o testelf-testelf.obj `if test -f 'testelf.c'; then $(CYGPATH_W) 'testelf.c'; else $(CYGPATH_W) '$(srcdir)/testelf.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testelf-testelf.Tpo $(DEPDIR)/testelf-testelf.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testelf.c' object='testelf-testelf.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testelf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testelf-testelf.obj `if test -f 'testelf.c'; then $(CYGPATH_W) 'testelf.c'; else $(CYGPATH_W) '$(srcdir)/testelf.c'; fi` testelf-demangle.o: demangle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testelf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testelf-demangle.o -MD -MP -MF $(DEPDIR)/testelf-demangle.Tpo -c -o testelf-demangle.o `test -f 'demangle.c' || echo '$(srcdir)/'`demangle.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testelf-demangle.Tpo $(DEPDIR)/testelf-demangle.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='demangle.c' object='testelf-demangle.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testelf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testelf-demangle.o `test -f 'demangle.c' || echo '$(srcdir)/'`demangle.c testelf-demangle.obj: demangle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testelf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testelf-demangle.obj -MD -MP -MF $(DEPDIR)/testelf-demangle.Tpo -c -o testelf-demangle.obj `if test -f 'demangle.c'; then $(CYGPATH_W) 'demangle.c'; else $(CYGPATH_W) '$(srcdir)/demangle.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testelf-demangle.Tpo $(DEPDIR)/testelf-demangle.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='demangle.c' object='testelf-demangle.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testelf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testelf-demangle.obj `if test -f 'demangle.c'; then $(CYGPATH_W) 'demangle.c'; else $(CYGPATH_W) '$(srcdir)/demangle.c'; fi` testelf-elfparser.o: elfparser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testelf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testelf-elfparser.o -MD -MP -MF $(DEPDIR)/testelf-elfparser.Tpo -c -o testelf-elfparser.o `test -f 'elfparser.c' || echo '$(srcdir)/'`elfparser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testelf-elfparser.Tpo $(DEPDIR)/testelf-elfparser.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elfparser.c' object='testelf-elfparser.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testelf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testelf-elfparser.o `test -f 'elfparser.c' || echo '$(srcdir)/'`elfparser.c testelf-elfparser.obj: elfparser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testelf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testelf-elfparser.obj -MD -MP -MF $(DEPDIR)/testelf-elfparser.Tpo -c -o testelf-elfparser.obj `if test -f 'elfparser.c'; then $(CYGPATH_W) 'elfparser.c'; else $(CYGPATH_W) '$(srcdir)/elfparser.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testelf-elfparser.Tpo $(DEPDIR)/testelf-elfparser.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elfparser.c' object='testelf-elfparser.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testelf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testelf-elfparser.obj `if test -f 'elfparser.c'; then $(CYGPATH_W) 'elfparser.c'; else $(CYGPATH_W) '$(srcdir)/elfparser.c'; fi` testunwind-testunwind.o: testunwind.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testunwind-testunwind.o -MD -MP -MF $(DEPDIR)/testunwind-testunwind.Tpo -c -o testunwind-testunwind.o `test -f 'testunwind.c' || echo '$(srcdir)/'`testunwind.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testunwind-testunwind.Tpo $(DEPDIR)/testunwind-testunwind.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testunwind.c' object='testunwind-testunwind.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testunwind-testunwind.o `test -f 'testunwind.c' || echo '$(srcdir)/'`testunwind.c testunwind-testunwind.obj: testunwind.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testunwind-testunwind.obj -MD -MP -MF $(DEPDIR)/testunwind-testunwind.Tpo -c -o testunwind-testunwind.obj `if test -f 'testunwind.c'; then $(CYGPATH_W) 'testunwind.c'; else $(CYGPATH_W) '$(srcdir)/testunwind.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testunwind-testunwind.Tpo $(DEPDIR)/testunwind-testunwind.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testunwind.c' object='testunwind-testunwind.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testunwind-testunwind.obj `if test -f 'testunwind.c'; then $(CYGPATH_W) 'testunwind.c'; else $(CYGPATH_W) '$(srcdir)/testunwind.c'; fi` testunwind-demangle.o: demangle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testunwind-demangle.o -MD -MP -MF $(DEPDIR)/testunwind-demangle.Tpo -c -o testunwind-demangle.o `test -f 'demangle.c' || echo '$(srcdir)/'`demangle.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testunwind-demangle.Tpo $(DEPDIR)/testunwind-demangle.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='demangle.c' object='testunwind-demangle.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testunwind-demangle.o `test -f 'demangle.c' || echo '$(srcdir)/'`demangle.c testunwind-demangle.obj: demangle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testunwind-demangle.obj -MD -MP -MF $(DEPDIR)/testunwind-demangle.Tpo -c -o testunwind-demangle.obj `if test -f 'demangle.c'; then $(CYGPATH_W) 'demangle.c'; else $(CYGPATH_W) '$(srcdir)/demangle.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testunwind-demangle.Tpo $(DEPDIR)/testunwind-demangle.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='demangle.c' object='testunwind-demangle.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testunwind-demangle.obj `if test -f 'demangle.c'; then $(CYGPATH_W) 'demangle.c'; else $(CYGPATH_W) '$(srcdir)/demangle.c'; fi` testunwind-elfparser.o: elfparser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testunwind-elfparser.o -MD -MP -MF $(DEPDIR)/testunwind-elfparser.Tpo -c -o testunwind-elfparser.o `test -f 'elfparser.c' || echo '$(srcdir)/'`elfparser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testunwind-elfparser.Tpo $(DEPDIR)/testunwind-elfparser.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elfparser.c' object='testunwind-elfparser.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testunwind-elfparser.o `test -f 'elfparser.c' || echo '$(srcdir)/'`elfparser.c testunwind-elfparser.obj: elfparser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testunwind-elfparser.obj -MD -MP -MF $(DEPDIR)/testunwind-elfparser.Tpo -c -o testunwind-elfparser.obj `if test -f 'elfparser.c'; then $(CYGPATH_W) 'elfparser.c'; else $(CYGPATH_W) '$(srcdir)/elfparser.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testunwind-elfparser.Tpo $(DEPDIR)/testunwind-elfparser.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='elfparser.c' object='testunwind-elfparser.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testunwind-elfparser.obj `if test -f 'elfparser.c'; then $(CYGPATH_W) 'elfparser.c'; else $(CYGPATH_W) '$(srcdir)/elfparser.c'; fi` testunwind-unwind.o: unwind.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testunwind-unwind.o -MD -MP -MF $(DEPDIR)/testunwind-unwind.Tpo -c -o testunwind-unwind.o `test -f 'unwind.c' || echo '$(srcdir)/'`unwind.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testunwind-unwind.Tpo $(DEPDIR)/testunwind-unwind.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind.c' object='testunwind-unwind.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testunwind-unwind.o `test -f 'unwind.c' || echo '$(srcdir)/'`unwind.c testunwind-unwind.obj: unwind.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT testunwind-unwind.obj -MD -MP -MF $(DEPDIR)/testunwind-unwind.Tpo -c -o testunwind-unwind.obj `if test -f 'unwind.c'; then $(CYGPATH_W) 'unwind.c'; else $(CYGPATH_W) '$(srcdir)/unwind.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/testunwind-unwind.Tpo $(DEPDIR)/testunwind-unwind.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind.c' object='testunwind-unwind.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(testunwind_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o testunwind-unwind.obj `if test -f 'unwind.c'; then $(CYGPATH_W) 'unwind.c'; else $(CYGPATH_W) '$(srcdir)/unwind.c'; fi` install-dist_pixmapsDATA: $(dist_pixmaps_DATA) @$(NORMAL_INSTALL) test -z "$(pixmapsdir)" || $(MKDIR_P) "$(DESTDIR)$(pixmapsdir)" @list='$(dist_pixmaps_DATA)'; test -n "$(pixmapsdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pixmapsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pixmapsdir)" || exit $$?; \ done uninstall-dist_pixmapsDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pixmaps_DATA)'; test -n "$(pixmapsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pixmapsdir)'; $(am__uninstall_files_from_dir) install-dist_pkgdataDATA: $(dist_pkgdata_DATA) @$(NORMAL_INSTALL) test -z "$(pkgdatadir)" || $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgdatadir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgdatadir)" || exit $$?; \ done uninstall-dist_pkgdataDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) install-dist_udevDATA: $(dist_udev_DATA) @$(NORMAL_INSTALL) test -z "$(udevdir)" || $(MKDIR_P) "$(DESTDIR)$(udevdir)" @list='$(dist_udev_DATA)'; test -n "$(udevdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(udevdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(udevdir)" || exit $$?; \ done uninstall-dist_udevDATA: @$(NORMAL_UNINSTALL) @list='$(dist_udev_DATA)'; test -n "$(udevdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(udevdir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__remove_distdir) dist-lzma: distdir tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma $(am__remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lzma*) \ lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(DATA) config.h installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pixmapsdir)" "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(udevdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_pixmapsDATA install-dist_pkgdataDATA \ install-dist_udevDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-dist_pixmapsDATA \ uninstall-dist_pkgdataDATA uninstall-dist_udevDATA .MAKE: all install-am install-strip .PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \ clean-binPROGRAMS clean-generic clean-noinstPROGRAMS ctags \ dist dist-all dist-bzip2 dist-gzip dist-lzip dist-lzma \ dist-shar dist-tarZ dist-xz dist-zip distcheck distclean \ distclean-compile distclean-generic distclean-hdr \ distclean-tags distcleancheck distdir distuninstallcheck dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am \ install-dist_pixmapsDATA install-dist_pkgdataDATA \ install-dist_udevDATA install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-dist_pixmapsDATA \ uninstall-dist_pkgdataDATA uninstall-dist_udevDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sysprof-1.2.0/sysprof-icon-48.png0000644000175000017500000000751312021176713013540 00000000000000PNG  IHDR00WgAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxZipU~s$!HJA "UBK20H:e;8 ҡEPT6e  )ddK;߁k& IEgzfޜs'>O7OH6@VEͫQx[ vx 2>>~|pp^^^-35553 rQ_cAȏG}0nݺz履~*{ݻgԬ-ӮZaX TYh<9p@}vv׷o. 4(9))iV5kExB.Ik+4_c߂ |`xέMkO:tշz˷qF_>}rqn4(&ߖ|3+@s͛PTTdcτ FVJ;wn p>tRM>qݲ|r {P7-DJ %?/4ճgOٺuk=?sɓ''8#&&fۊ+vk׮eܹ3?i[p_5RQ&?Ng$nݺugᑈ@ R__/E<;w~`ԩSmhh(ϤLdЛĮ% \/^ '''/ljj`(=s# (T E}/?tm]7=77Dps ` IddJqq1ullvtff7,1mёΘ1m/ RgJ\\F#L*++9NkسٳGt>k!؝QUU*|x?RHHHFhhhP/'(}cc I  SL1\dɒx_f<Р32lٲC祢b52vXȑ#МyŴIdd$ @r\jgSf̘{5X4*HB03g.bjʹsRRR~|':Ed ED Ug!RZؗ2=zd&G%;uF.mfmNU >@.\ȂF A׿JMM\1hg}&gΜQnK),(SDeĈ2iҤ'Nok̓j!ҥ˶ӧ|$`|}$ JhD5Jܶnb b'Riɑ7o{ 2_]]\PὛ#״WʻBN:o߾2qDa2"֭ǏQ*+7W\.Ô. 卯$ʓ-syZ$??_A0=r꫃~u|yʱ0P˄pA2kɕ+Wkq[" "DY 7EBaCd JAWe#)VFB*˨,*QM=f07 @棢k׮/W2IJ .!| l*B2Ж],T%;UyY ލFk׮?i q21z*7̠ }'OTd%?,\C}Dt GfRj:Ldho"Cz$D9'CBbSkIttb˄4Hfhÿ&Ϡmڼe8#(s#l/I ƻC("58IH( u;}$"r~8boeddd̘1tKJeL @`qE30laM`Q'g F8n *.NSalJֲԱlA93xR$EoŰ iɰj8/o'kaqoXahg)+C®CL-wYC4)--Uq>h y  lVYDB?XLaƽN<Ӈq|I`ѣUjk׮ȼpX"W )4¤5@pߌH{z)I}]>V thYJWpy%LMD*Ku,]{@c04 r&BonZ'v%-f5g0 k)P{NS3ؒgpzd 4T=1͟PHɋ/.!CG+.,w E42Gv`KgF^Y2͋^ТZE053mHnGDDʛoqh^ps&7|xeF 6u@1Kf6fe)-^CG^-{ OUS^SityahU:;A5ddZniQ"7 aܚ!jJ`S3r*h?B1cS H(ti3jr,;;[(6IeCj 7!-}||2y>nCЉԣL3rxrÄ0DE{jM}ubi=h:I!l@(x`̴=`?n\*}8dTT hd-C QN̊gA#TdN;#8M{ iȔr0^VHZ%PqLyɀDXg0)E(޽{w})PL׏uzһo߾ QBeܾ9Y< R `²֠ .4Q82^]g0}TTs5eDG)iƍW^gϞ=bz(lp=t( F^]g[MnU6I=^wCV.cBZaSwdsKA6G5"*S)F{D qOA<9PbY`/23mW\7ާO4ZW E{3*A$zBᘅ#/h>E׌H &?9%97 tʰ?TjWp=K4MsNlP@SFyGqNCqǎ! UJ P3tM$yp\, X& ͋USdB\?,x<ŹrܥKYUǎۣrlG&Z .,CWǩ8p w {ĔYwȵ29ր9p\MWQ IhQ)S=tbttgΜsfZb~njvYNxh|oF ᐊs"'δ vK/Nz\"*BbCJBMwe~zټyZ ={6.{.{JgDuw7n\:)+++YIQcCp~3r֞I+RaMLL,/YsgOmFB< Zp?ݩ )α34VgcYPCHl2鏆|"$q$v09fIrIENDB`sysprof-1.2.0/TODO0000644000175000017500000020150612021176713010634 00000000000000Before 1.1: * Move perfcounter.h into sysprof namespace * Check for existence and presense of __NR_perf_counter_open in syscall.h Before 1.2: * Filter out kernel stacktrace entries from the interrupts. (This can be done better in the kernel). * Make sure errors are reported properly. * Fork GtkLabel and change it to only request a resize when the new size is actually larger than the old one. It could also be special-purposed for the "Samples: " format with the number left-aligned. * When should the samples label be updated? On one hand we don't want it to be the only thing that shows up on the profile. On the other, when there are things going on, it should update quickly. It is also desirable that it updates slowly if there is slow activity going on; for example if you are moving the mouse cursor around. Cost of updating the samples label: s (in samples) Base rate: f If we update the samples label c times per second, the frequency is c * s If we update the samples label for every k samples. (k - s)/f is the time it takes before updating So if the update rate should be proportional to the base rate, then we get (k - s)/f = d/f which implies k = d + s. So we should pick some constant d and only update when that many samples have arrived. * The counters seem to not be disabled when looking at the profiles. * Build system - Create RPM package? See fedora-packaging-list for information about how to package kernel modules. Lots of threads in June 2005 and forward. See also http://www.fedoraproject.org/wiki/Extras/KernelModuleProposal Someone already did create a package - should be googlable. * The hrtimer in the kernel currently generates an event every time the timer fires. There are two problems with this: - Essentially all the events are idle events and exclude_idle is ignored. - If you make it obey exclude_idle, it still generates activity based on what is running currently. Unfortunately, the thing that is running will very often be the userspace tracker because it was handling the last sample generated. So this degenerates into an infinite loop of sorts. Or maybe the GUI is just too slow, but then why doesn't it happen with the real counters? I think the solution here is to make the hrtimer fire at some reasonable interval, like 100000 ns. When the timer fires, if the current task is not the idle taks, it increments a counter by cpu clock frequency * 100000 ns If that overflows the sample period, an event is generated. This is closer to the idea of a fake CPU cycle counter. Also, for reasons I don't understand, it stops generating events completely if a process is running that spins on all CPUs. So this interface is not usable in its present state, but fortunately all CPUs we care about have hardware cycle counters. * With more than one CPU, we can get events out of order, so userspace will have to deal with that. With serial numbers we could do it correctly, but even without them we can do a pretty reasonable job of putting them back in order. If a fork happens "soon" after a sample, it probably happened before the sample; if an mmap happens "soon" after a sample that would otherwise be unmapped, it probably happened before the sample. All we need is a way to determine what "soon" is. Serial numbers would be useful to make "soon" an accurate measure. There is also the issue of pid reuse, but that can probably be ignored. If we ignore pid reuse, we can sort the event buffer where two events compare equal, unless both have the same pid and one is a fork and the other is not. A system-wide serial number could be expensive to maintain though, so maybe time events would be just as good. * Another issue is processes that exit during the initial scan of /proc. Such a process will not cause sample events by itself, but it may fork a child that will. There is no way to get maps for that child. A possible solution would be to optionally generate mmap event after forks. Userspace would turn this off when it was done with the initial gathering of processes. Also, exec() events will delete the maps from a process, but all we get is 'comm' events which is not quite the same thing. * Find out why the busy cursor stays active after you hit start * Kernel binary when available, is better than kallsyms. * GTK+ bugs: - Misposition window after click - Find out why gtk_tree_view_columns_autosize() apparently doesn't work on empty tree views. - Write my own tree model? There is still performance issues in FooTreeStore. * Counters must not be destroyed during tracker setup. They have to exist but be disabled so that we can track process creation. * Check that we don't use too much memory (in particular with the timeline). * Fix names. "new process" is really "exec". (What does "comm" actually stand for? Command?) * Fix ugly flash when double clicking in descendants view * Find out what's up with weird two-step flash when you hit start when a profile is loaded. * Make tracker creation faster. (Faster populating mainly) * Share map reading code between vdso stuff in binfile.c and tracker.c * Get rid of remaining gulongs (use uint64_t instead) * Move binfile hash table to state_t. * Get rid of process.c * On 32 bit, NMI stackframes are not filtered out which leads to wrong kernel traces * Can we track kernel modules being inserted/removed? * Does it make sense to try and locate a kernel binary, or can we always just use kallsyms. * open_inode() would be useful in many cases * Is the double mapping of the ring buffer ok? * Why do we get EINVAL when we try to track forks? * Sometimes it gets samples for unknown processes. This may be due to forking without execing. * Give an informative error message if not run as root * What are the events generated for pid 0 and pid 1? They have no stacktrace, and an eip in the kernel. * Delete the binparser stuff and fix the elf parser to just deal with 32 bits vs 64 bits. Or use C++ like behdad does in harfbuzz? * We often get "No map". I suspect this is because the vdso stackframe is strange. * Hack to disable recursion for binaries without symbols causes the symbols to not work the way other symbols do. A better approach is probably to simply generate a new symbol for every appearance except leaf nodes, which should still be considered one symbol (or maybe be considered the same symbol if they have the same parent). In fact "has same parent" may be the correct criterion in all cases. (done: master now doesn't fold those recursions anymore) * See if we can make "In file " not be treated as a recursive function. Maybe simply treat each individual address in the file as a function. Or try to parse the machine code. Positions that are called are likely to be functions. - Treat identical addresses as one function - Treat all addresses within a library that don't have children are treated as one function. This will have the effect of coalescing adjacent siblings without children. Which is what you want since you can't tell them apart anyway. It will never be a great experience though. * Make sure that labels look decent in case of "No Map" etc. * Elf bugs: - error handling for bin_parser is necessary. * Find out why all apps have an "In file /usr/bin/" below _libc_main. If possible, maybe make up a name for it. * vdso stuff: - the "[vdso]" string should be #defined somewhere - Does get_vdso_bytes() belong in process.c? - Is basing on "[vdso]" always correct? * Convert things like [heap] and [stack] to more understandable labels. * Strategies for taking reliable stacktraces. Three different kinds of files - kernel - vdso - regular elf files - kernel - eh_frame annotations, in kernel or in kernel debug - /proc/kallsyms - userspace can look at _stext and _etext to determine start and end of kernel text segment - copying kernel stack to userspace - it's always 4096 bytes these days - heuristically determine functions based on address - callbacks on the stack can be identified by having an offset of 0. - even so there is a lot of false positives. - is eh_frame usually loaded into memory during normal operation? It is mapped, but probably not paged in, so we will be taking a few major page faults when we first profile something. Unless of course, we store the entire stack in the stackstash. This may use way too much memory though. - Locking, possibly useful code: /* In principle we should use get_task_mm() but * that will use task_lock() leading to deadlock * if somebody already has the lock */ if (spin_is_locked (¤t->alloc_lock)) printk ("alreadylocked\n"); { struct mm_struct *mm = current->mm; if (mm) { printk (KERN_ALERT "stack size: %d (%d)\n", mm->start_stack - regs->REG_STACK_PTR, current->pid); stacksize = mm->start_stack - regs->REG_STACK_PTR; } else stacksize = 1; } - regular elf - usually have eh_frame section which is mapped into memory during normal operation - do stackwalk in kernel based on eh_frame - eh_frame section is usually mapped into memory, so no file reading in kernel would be necessary. - do stackwalk in userland based on eh_frame - do ebp based stackwalk in kernel - do ebp based stackwalk in userland - do heuristic stackwalk in kernel - do heuristic stackwalk in userland - Send heuristic stack trace to user space, along with location on the stack. Then, in userspace analyze the machine code to determine the size of the stack frame at any point. The instructions that would need to be recognized are: subl , %esp addl , %esp leave jcc push pop GCC is unlikely to have different stack sizes at the entry to a basic block. We can often find a vmlinux in /lib/modules//build. * "Expand all" is horrendously slow because update_screenshot gets called for every "expanded" signal. In fact even normal expanding is really slow. It's probably hopeless to get decent performance out of GtkTreeView, so we will have to store a list of expanded objects and keep that uptodate as the rows expands and unexpands. * Give more sensible 'error messages'. Eg., if you get permission denied for a file, put "Permission denied" instead of "No map" * crc32 checking probably doesn't belong in elfparser.c * Missing things in binparser.[ch] - it's inconvenient that you have to pass in both a parser _and_ a record. The record should just contain a pointer to the parser. On the other hand, the result does depend on the parser->offset. So it's a bit confusing that it's not passed in. - the bin_parser_seek_record (..., 1); idiom is a little dubious - Add error checking Also need to add error checking. - "native endian" is probably not useful. Maybe go back to just having big/little endian. Should probably rethink the whole thing. It's just not very convenient to use, even for simple things like ELF files. * Rename stack_stash_foreach_by_address() to stack_stash_foreach_unique(), or maybe not ... Which things are we actually using from stack stash now? * Maybe report idle time? Although this would come for free with the timelines. * Fix (deleted) problem. But more generally, whenever we can't display a symbol, display an error message instead, ie., - 'Binary file was deleted/replaced' - 'No mapping for address' - 'No symbols in binary file' - 'Address has no corrresponding symbol in file' - etc. done: HEAD will not load files with the wrong inode now. * Consider whether ProfileDescendant can be done with a StackStash We need the "go-back-on-recursion" behavior. That could be added of course ... the functions are otherwise very similar. * Add spew infrastructure to make remote debugging easier. * Make it compile and work on x86-64 - make the things we put in a stackstash real objects so that - we can save them - they will know how to delete the presentation names and themselves (through a virtual function) - they can contain markup etc. - The unique_dup() scheme is somewhat confusing. - a more pragmatic approach might be to just walk the tree and save it. - plug all the leaks - loading and saving probably leak right now - make it use less memory: - StackNodes are dominating - fold 'toplevel' into 'size' - allocate in blocks - this will need to be coordinated with profile.c which also creates stacknodes. - maybe simply make stackstashes able to save themselves. - rethink loading and saving. Goals - Can load 1.0 profiles - Don't export too much of stackstashes to the rest of the app Features: * Have a compatibility module that can load 1.0 modules - reads in the call tree, then generate a stack stash by repeatedly adding traces. * Make stackstash able to save themselves using callbacks. * If loading a file fails, then try loading it using the 1.0 loader. - optimization: make sure we fail immediately if we see an unknown object. * Add versioning support to sfile.[ch]: - sformat_new() should take doctype and version strings: like "sysprof-profile" "version 1.2" - there should be sfile_sniff() functionality that will return the doctype and version of a file. Or None if there aren't any. * At this point, make the loader first check if the file has a version if it doesn't, load as 1.0, otherwise as whatever the version claims it is. * Make provisions for forward compatibility: maybe it should be possible to load records with more fields than specified. * Figure out how to make sfile.[ch] use less memory. - In general clean sfile.[ch] up a little: - split out dfa in its own generic class - make a generic representation of xml files with quarks for strings: struct item { int begin/end/text; quark text: -> begin/end/value int id; -> for begins that are pointed to } perhaps even with iterators. Should be compact and suitable for both input and output. As a first cut, perhaps just split out the Instruction code. (done, somewhat). - make the api saner; add format/content structs Idea: all types have to be declared: SFormat *format = sformat_new() SType *object_list = stype_new (format); SType *object = stype_new (format); ... stype_define_list (object_list, "objects", object); stype_define_record (object, "object", name, total, self, NULL); stype_define_pointer (...); * See if the auto-expanding can be made more intelligent - "Everything" should be expanded exactly one level - all trees should be expanded at least one level * Send entire stack to user space, then do stackwalking there. That would allow us to do more complex algorithms, like dwarf, in userspace. Though we'd lose the ability to do non-racy file naming. We could pass a list of the process mappings with each stack though. Doing this would also solve the problem of not being able to get maps of processes running as root. Might be too expensive though. User stacks seem to be on the order of 100K usually, which for 200 times a second means a bandwidth of 20MB/s, which is probably too much. One question is how much of it usually changes. Actually it seems that the _interesting_ part of the stack (ie., from the stack pointer and up) is not that big in many cases. The average stacksize seemed to be about 7700 bytes for gcc compiling gtk+. Even deeply recursive apps like sysprof only generate about 55K stacks. Other possibilities: - Do heuristic stack walking where it lists all words on the stack that look like they might be return addresses. - Somehow map the application's stack pages into the client. This is likely difficult or impossible. - Another idea: copy all addresses that look like they could be return addresses, along with the location on the stack. This just might be enough for a userspace stack walker. - Yet another: krh suggests hashing blocks of the stack, then only sending the blocks that changed since last time. - every time you send a stackblock, also send a cookie. - whenever you *don't* send a stackblock, send the cookie instead. That way you always get a complete stacktrace conceptually. - also, that would allow the kernel to just have a simple hashtable containing the known blocks. Though, that could become large. Actually there is no reason to store the blocks; you can just send the hashcode. That way you would only need to store a list of hashcodes that we have generated previously. - One problem with doing DWARF walking is that the debug code will have to be faulted in. This can be a substantial amount of disk access which is undesirable to have during a profiling run. Even if we only have to fault in the .eh_frame_hdr section, that's still 18 pages for gtk+. The .eh_frame section for gtk+ is 72 pages. A possibility may be to consider two stacktraces identical if the only differing values are *outside* the text segments. This may work since stack frames tend to be the same size. Is there a way of determining the location of text segments without reading the ELF files? Maybe just check if it's inside an executable mappign. It is then sufficient in user space to only store one representative for each set of considered-identical stack traces. User space storage: Use the stackstash tree. When a new trace is added, just skip over nodes that differ, but where none of them points to text segments. Two possibilities then: - when two traces are determined to differ, store them in completely separate trees. This ensures that we will never run the dwarf algorithm on an invalid stack trace, but also means that we won't get shared prefixes for stacktraces. - when two traces are determined to differ, branch off as currently. This will share more data, but the dwarf algorithm could be run on invalid traces. It may work in practice though if the compiler generally uses fixed stack frames. A twist on is to mark the complete stack traces as "complete". Then after running the DWARF algorithm, the generated stack trace can be saved with it. This way incomplete stack traces branching off a complete one can be completed using the DWARF information for the shared part. * Notes on heuristic stack walking - We can reject addresses that point exactly to the beginning of a function since these are likely callbacks. Note though that the first time a function in a shared library is called, it goes through dynamic linker resolution which will cause the stack to contain a callback of the function. This needs to be investigated in more detail. - We are already rejecting addresses outside the text section (addresses of global variables and the like). * How to get the user stack: /* In principle we should use get_task_mm() but * that will use task_lock() leading to deadlock * if somebody already has the lock */ if (spin_is_locked (¤t->alloc_lock)) printk ("alreadylocked\n"); { struct mm_struct *mm = current->mm; if (mm) { printk (KERN_ALERT "stack size: %d (%d)\n", mm->start_stack - regs->REG_STACK_PTR, current->pid); stacksize = mm->start_stack - regs->REG_STACK_PTR; } else stacksize = 1; } * If interrupt happens in kernel mode, send both kernel stack and user space stack, have userspace stitch them together. well, they could be stitched together in the kernel. Already done: we now take a stacktrace of the user space process when the interrupt happens in kernel mode. (Unfortunately, this causes lockups on many kernels (though I haven't seen that for a while)). We don't take any stacktraces of the kernel though. Things that need to be investigated: - does the kernel come with dwarf debug information? - does the kernel come with some other debug info - is there a place where the vmlinux binary is usually placed? (We should avoid any "location of vmlinux" type questions if at all possible). We do now copy the kernel stack to userspace and do a heuristic stack walk there. It may be better at some point to use dump_trace() in the kernel since that will do some filtering by itself. Notes about kernel symbol lookup: - /proc/kallsym is there, but it includes things like labels. There is no way to tell them from functions - We can search for a kernel binary with symbols. If the kernel-debug package is installed, or if the user compiled his own kernel, we will find one. This is a regular elf file. It also includes labels, but we can tell by the STT_INFO field which is which. Note though that for some labels we do actually want to treat them as functions. For example the "page_fault" label, which is function by itself. We can recognize these by the fact that their symbols have a size. However, the _start function in normal applications does not have a size, so the heuristic should be something like this: - If the address is inside the range of some symbol, use that symbol - Otherwise, if the closest symbol is a function with size 0, use that function. This means the datastructure will probably have to be done a little differently. - See if there is a way to make it distcheck - grep "FIXME - not10" - grep FIXME - translation should be hooked up - Consider adding "at least 5% inclusive cost" filter - consider having the ability to group a function together with its nearest neighbours. That way we can eliminate some of the effect of "one function taking 10% of the time" vs. "the same function broken into ten functions each taking 1%" Not clear what the UI looks like though. - Ability to generate "screenshots" suitable for mail/blog/etc UI: "generate screenshot" menu item pops up a window with a text area + a radio buttons "text/html". When you flick them, the text area is automatically updated. - beginning in CVS: - why does the window not remember its position when you close it with the close button, but does remember it when you use the wm button or the menu item? It actually seems that it only forgets the position when you click the button with the mouse. But not if you use the keyboard ... This is a gtk+ bug. - Find out how gdb does backtraces; they may have a better way. Also find out what dwarf2 is and how to use it. Look into libunwind. It seems gdb is capable of doing backtraces of code that neither has a framepointer nor has debug info. It appears gdb uses the contents of the ".eh_frame" section. There is also an ".eh_frame_hdr" section. http://www.linuxbase.org/spec/booksets/LSB-Embedded/LSB-Embedded/ehframe.html look in dwarf2-frame.[ch] in the gdb distribution. Also look at bozo-profiler http://cutebugs.net/bozo-profiler/ which has an elf32 parser/debugger - Make busy cursors more intelligent - when you click something in the main list and we don't respond within 50ms (or perhaps when we expect to not be able to do so (can we know the size in advance?)) - instead of what we do now: set the busy cursor unconditionally - Consider adding ability to show more than one function at a time. Algorithm: Find all relevant nodes; For each relevant node best_so_far = relevant node walk towards root if node is relevant, best_so_far = relevant add best_so_far to interesting for each interesting list leaves for each leaf add trace to tree (leaf, interesting) - Consider adding KDE-style nested callgraph view - probably need a dependency on gtk+ 2.8 (cairo) for this. - Matthias has code for something like this. - See http://www.marzocca.net/linux/baobab.html - Also see http://www.cs.umd.edu/hcil/treemap-history/index.shtml - Add support for line numbers within functions - Possibly a special "view details" mode, assuming that the details of a function are not that interesting together with a tree. (Could add radio buttons somewhere in in the right pane). Or tabs. - Open a new window for the function. - Add view->ancestors/descendants menu items - rethink caller list, not terribly useful at the moment. Federico suggested listing all ancestors. Done: implemented this idea in CVS HEAD. If we keep it that way, should do a globale s/callers/ancestors on the code. - not sure it's an improvement. Often it is more interesting to find the immediate callers. - Now it's back to just listing the immediate callers. - Figure out how Google's pprof script works. Then add real call graph drawing. (google's script is really simple; uses dot from graphviz). KCacheGrind also uses dot to do graph drawing. - hide internal stuff in ProfileDescendant Later: - Multithreading is possible in a number of places. - If the stack trace ends in a memory access instruction, send the vma information to userspace. Then have user space produce statistics on what types of memory are accessed. - somehow get access to VSEnterprise profiler and see how it works. somehow get access to vtune and see how it works. - On SMP systems interrupts happen unpredictably, including when another one is running. Right now we are ignoring any interrupts that happen when another one is running, but we should probably just save the data in a per-cpu buffer. - Find out if sysprof accurately reports time spent handling pagefaults. There is evidence that it doesn't: - a version of sysprof took 10 seconds to load a certain profile. Profiling itself it appeared that most of the time was spent in the GMarkup parser - a newer version of sysprof with significantly more compact Instructions structure took about 5 seconds, but the profile looked about the same. The difference between the two versions has to be in page faults/ memory speed, but the profiles looked similar. Try and reproduce this in a more controlled experiment. - See if it is possible to group the X server activity under the process that generated it. - .desktop file [Is this worth it? You will often want to start it as root, and you will need to insert the module from the comman line] - Applications should be able to say "start profiling", "stop profiling" so that you can limit the profiling to specific areas. Idea: Add a new kernel interface that applications uses to say begin/end. Then add a timeline where you can mark interesting regions, for example those that applications have marked interesting. - Find out how to hack around gtk+ bug causing multiple double clicks to get eaten. - Consider what it would take to take stacktraces of other languages such as perl, python, java, ruby, or bash. Or scheme. Possible solution is for the script binaries to have a function called something like __sysprof__generate_stacktrace (char **functions, int *n_functions); that the sysprof kernel module could call (and make return to the kernel). This function would behave essentially like a signal handler: couldn't call malloc(), couldn't call printf(), etc. Note though that scripting languages will generally have a stack with both script-binary-stack, script stack, and library stacks. We wouldn't want scripts to need to parse dwarf. Also if we do that thing with sending the entire stack to userspace, things will be further complicated. Also note languages like scheme that uses heap allocated activation records. - Consider this usecase: Someone is considering replacing malloc()/free() with a freelist for a certain data structure. All use of this data structure is confined to one function, foo(). It is now interesting to know how much time that particular function spends on malloc() and free() combined. Possible UI: - Select foo(), - find an instance of malloc() - shift-click on it, - all traces with malloc are removed - a new item "..." appears immeidately below foo() - malloc is added below "..." - same for free - at this point, the desired data can be read at comulative for "..." Actually, with this UI, you could potentially get rid of the caller list: Just present the call tree under an root, and use ... to single out the stuff you are interested in. Maybe also get rid of 'callers' by having a new "show details" dialog or something. The complete solution here degenerates into "expressions": "foo" and ("malloc" or "free") Having that would also take care of the "multiple functions" above. Noone would understand it, though. - figure out a way to deal with both disk and CPU. Need to make sure that things that are UNINTERRUPTIBLE while there are RUNNING tasks are not considered bad. Also figure out how to deal with more than one CPU/core. Not entirely clear that the sysprof visualization is right for disk. Maybe assign a size of n to traces with n *unique* disk access (ie. disk accesses that are not required by any other stack trace). Or assign values to nodes in the calltree based on how many diskaccesses are contained in that tree. Ie., if I get rid of this branch, how many disk accesses would that get rid of. Or turn it around and look at individual disk accesses and see what it would take to get rid of it. Ie., a number of traces are associated with any given diskaccess. Just show those. Or for a given tree with contained disk accesses, figure out what *other* traces has the same diskaccesses. Or visualize a set of squares with a color that is more saturated depending on the number of unique stack traces that access it. Then look for the lightly saturated ones. The input to the profiler would basically be (stack trace, badness, cookie) For CPU: badness=10ms, cookie= For Disk: badness=, cookie= For Memory: badness=, cookie= Cookies are used to figure out whether an access is really the same, ie., for two identical cookies, the size is still just one, however Memory is different from disk because you can't reasonably assume that stuff that has been read will stay in cache (for short profile runs you can assume that with disk, but not for long ones). - Perhaps show a timeline with CPU in one color and disk in one color. Allow people to look at at subintervals of this timeline. Is it useful to look at both CPU and disk at the same time? Probably not. See also marker discussion above. UI should probably allow double clicking on a marked section and all instances of that one would be marked. - This also allows us to show how well multicore CPUs are being used. - Other variation on the timeline idea: Instead of a disk timeline you could have a list of individual diskaccesses, and be able to select the ones you wanted to get rid of. - The existing sysprof visualization is not terribly bad, the "self" column is more useful now. - See what files are accessed so that you can get a getter idea of what the system is doing. - Optimization usecases: - A lot of stuff is read synchronously, but it is possible to read it asynchronously. Visualization: A timeline with alternating CPU/disk activity. - What function is doing all the synchronous reading, and what files/offsets is it reading. Visualization: lots of reads across different files out of one function - A piece of the program is doing disk I/O. We can drop that entire piece of code. Sysprof visualization is ok, although seeing the files accessed is useful so that we can tell if those files are not just going to be used in other places. (Gnumeric plugin_init()). - A function is reading a file synchronously, but there is other (CPU/disk) stuff that could be done at the same time. Visualization: A piece of the timeline is diskbound with little or no CPU used. - Want to improve code locality of library or binary. Visualization: no GUI, just produce a list of functions that should be put first in the file. Then run the program again until the list converges. (Valgrind may be more useful here). - Nautilus reads a ton of files, icons + all the files in the homedirectory. Normal sysprof visualization is probably useful enough. - Profiling a login session. - Many applications are running at the same time, doing IPC. It would be useful if we could figure out what other things a given process is waiting on. Eg., in poll, find out what processes have the other ends of the fd's open. Visualization: multiple lines on a graph. Lines join up where one process is blocking on another. That would show processes holding up the progress very clearly. This was suggested by Federico. - Need to report stat() as well. (Where do inode data end up? In the buffer-cache?) Also open() may cause disk reads (seeks). - To generate the timeline we need to know when a disk request is issued and when it is completed. This way we can assign blame to all applications that have issued a disk request at a given point in time. The disk timeline should probably vary in intensity with the number of outstanding disk requests. -=-=-=-=-=-=-=-=-=-=-=-=-=-=- ALREADY DONE: -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * Find out what is going on with kernel threads: [(ksoftirqd/0)] 0.00 0.03 No map ([(ksoftirqd/0)]) 0.00 0.03 kernel 0.00 0.03 do_softirq 0.00 0.03 __do_softirq 0.00 0.03 * Make sure there aren't leftover stacktraces from last time when profiling begins. * Is the move-to-front in process_locate_map() really worth it? * Whenever we fail to lock the atomic variable, track this, and send the information to userspace as an indication of the overhead of the profiling. Although there is inherent aliasing here since stack scanning happens at regular intervals. * Apparently, if you upgrade the kernel, then don't re-run configure, the kernel Makefile will delete all of /lib/modules//kernel if you run make install in the module directory. Need to find out what is going on. * Performance: Switching between descendant views is a slow: - gtk_tree_store_get_path() is O(n^2) and accounts for 43% of the time. - GObject signal emission overhead accounts for 18% of the time. Consider adding a forked version of GtkTreeStore with performance and bug fixes. * If we end up believing the kernel's own stacktraces, maybe /proc/kallsyms shouldn't be parsed until the user hits profile. * Make it compilable against a non-running kernel. * With kernel module not installed, select Profiler->Start, then dismiss the alert. This causes the start button to appear prelighted. Probably just another gtk+ bug. - Fix bugs/performance issues: - add_trace_to_tree() might be a little slow when dealing with deeply recursive profiles. Hypothesis: seen_nodes can grow large, and the algorithm is O(n^2) in the length of the trace. - Have kernel module report the file the address was found in Should avoid a lot of potential broken/raciness with dlopen etc. Probably better to send a list of maps with each trace. Which shouldn't really be that expensive. We already walk the list of maps in process_ensure_map() on every trace. And we can do hashing if it turns out to be a problem. Maybe replace the SysprofStackTrace with a union, so that it can be either a list of maps, or a stacktrace. Both map lists and stacktraces would come with a hashcode.allowing userspac. This avoids the problem that maps could take up a lot of extra bandwidth. struct MapInfo { long start; long end; long offset; long inode; } struct Maps { int hash_code; int n_maps; MapInfo info [127]; char filenames [2048]; } - possibly add dependency on glib 2.8 if it is released at that point. (g_file_replace()) * Some notes about timer interrupt handling in Linux On an SMP system APIC is used - the interesting file is arch/i386/kernel/apic.c On UP systems, the normal IRQ0 is used When the interrupt happens, entry.S calls do_IRQ, which sets up the special interrupt stack, and calls __do_IRQ, which is in /kernel/irq/handle.c. This calls the corresponding irqaction, which has previously been setup by arch/i386/mach-default/setup.c to point to timer_interrupt, which is in arch/i386/kernel/time.c. This calls do_timer_interrupt_hooks() which is defined in /include/asm-i386/mach-default/do_timer.h. This function then calls profile_tick(). Note when the CPU switches from user mode to kernel mode, it pushes SS/ESP on top of the kernel stack, but when it switches from kernel mode to kernel mode, it does _not_ push SS/ESP. It does in both cases push EIP though. * Rename sysprof-text to sysprof-cli * Find out why the samples label won't right adjust * It crashes sometimes. I haven't seen any crashes in a long time * Find out why the strings _ZL11DisplayLineP20nsDisplayListBuilderRK6nsRectS3_R19nsLineList_iteratoriRiRK16nsDisplayListSetP12nsBlockFrame _ZL11DisplayRowsP20nsDisplayListBuilderP7nsFrameRK6nsRectRK16nsDisplayListSet _ZL11DrawBordersP10gfxContextR7gfxRectS2_PhPdS4_PjPP14nsBorderColorsijiP6nsRect _ZL11HandleEventP10nsGUIEvent _ZL12IsContentLEQP13nsDisplayItemS0_Pv _ZL15expose_event_cbP10_GtkWidgetP15_GdkEventExpose do not get demangled. * For glibc, the debug files do not contain .strtab and .symtab, but the original files do. The algorithm in binfile.c must be modified accordingly. * If we profile something that is not very CPU bound, sysprof itself seems to get a disproportionate amount of the samples. Should look into this. Fixed by only returning from poll when there is more than eight traces available. * regarding crossing system call barriers: Find out about the virtual dso that linux uses to do fast system calls: http://lkml.org/lkml/2002/12/18/218 and what that actually makes the stack look like. (We may want to just special case this fake dso in the symbol lookup code). Maybe get_user_pages() is the way forward at least for some stuff. note btw. that the kernel pages are only one or two pages, so we could easily just dump them to userspace. * In profile.c, change "non_recursive" to "cumulative", and "marked_non_recursive" to a boolean "charged". This is tricky code, so be careful. Possibly make it a two-pass operation: - first add the new trace - then walk from the leaf, charging nodes That would allow us to get rid of the marked field altogether. In fact, maybe the descendants tree could become a stackstash. We'll just have to make stack_stash_add_trace() return the leaf. DONE: the name is now "cumulative" * vdso - assume its the same across processes, just look at sysprof's own copy. Done: vdso is done now - send copy of it to userspace once, or for every sample. * Various: - decorate_node should be done lazily - Find out why we sometimes get completely ridicoulous stacktraces, where main seems to be called from within Xlib etc. This happens even after restarting everything. - It looks like the stackstash-reorg code confuses "main" from unrelated processes. - currently it looks like if multiple "main"s are present, only one gets listed in the object list. Seems to mostly happen when multiple processes are involved. - Numbers in caller view are completely screwed up. - It looks like it sometimes gets confused with similar but different processes: Something like: process a spends 80% in foo() called from bar() process b spends 1% in foo() called from baz() we get reports of baz() using > 80% of the time. Or something. * commandline version should check that the output file is writable before starting the profiling. * See if we can reproduce the problem where libraries didn't get correctly reloaded after new versions were installed. This is just the (deleted) problem. Turns out that the kernel doesn't print (deleted) in all cases. Some possibilities: - check that the inodes of the mapped file and the disk file are the same (done in HEAD). - check that the file was not modified after being mapped? (Can we get the time it was mapped or opened?) If it was modified you'd expect the inode to change, right? * Find out if the first sort order of a GtkTreeView column can be changed programmatically. It can't (and the GTK+ bug was wontfixed). A workaround is possible though. (Someone, please write a GtkTreeView replacement!) * Missing things in binparser.[ch] - maybe convert BIN_UINT32 => { BIN_UINT, 4 } we already have the width in the struct. * Rethink binparser. Maybe the default mode should be: - there is a current offset - you can move the cursor - _goto() - _align() - you can read structs with "begin_struct (format) / end_struct()" Or maybe just "set_format()" that would accept NULL? - when you are reading a struct, you can skip records with _index() - you can read fields with get_string/get_uint by passing a name. - you can read anonymous strings and uints by passing NULL for name This is allowed even when not reading structs. Or maybe this should be separate functions. Advantages: - they can skip ahead, unlike fields accessors - you can access specific types (8,16,32,64) - there is no "name" field Disadvantage: - the field accesors would need renaming. bin_parser_get_uint_field () is not really that bad though. Maybe begin_record() could return a structure you could use to access that particular record? Would nicely solve the problems with "goto" and "index". bin_record_get_uint(); What should begin/end be called? They will have different objects passed. bin_parser_get_record (parser) -> record bin_record_free (record); - Maybe support for indirect strings? Ie., get_string() in elfparser - This will require endianness to be a per-parser property. Which is probably just fine. Although d-bus actually has per-message endianness. Maybe there could be a settable "endianness" property. * Don't look in $(libdir) for separate debug files (since $libdir is the libdir for sysprof, not a system wide libdir). Tim Rowley. Fix is probably to hardcode /usr/lib, and also look in $libdir. * Consider deleting cmdline hack in process.c and replace with something at the symbol resolution level. Will require more memory though. DONE: in head, processes are no longer coalesced based on cmdline. Need to add something at the symbol level. * don't loop infinitely if there are cycles in the debuglink graph. * Add "sysprof --version" * Fix (potential) performance issues in symbol lookup. - when an elf file is read, it should be checked that the various sections are of the right type. For example the debug information for emacs is just a stub file where all the sections are NOBITS. * Try reproducing crash when profiling xrender demo - it looks like it crashes when it attempts to read /usr/bin/python - apparently what's going on is that one of the symbols in python's dynamic symbol table has a completely crazy 'st_name' offset. DONE: we didn't actually need to read the name at all, but still should find out why that value is so weird. It looks like there is something strange going on with that file. All the dynsyms have weird info/type values, yet nm and readelf have no problems displaying it. - Can .gnu_debuglink recurse? yes, it can, and we should probably not crash if there are cycles in the graph. * Find out why we are getting bogus symbols reported for /usr/bin/Xorg Like this: Everything 0.00 100.00 [/usr/bin/Xorg] 0.00 94.79 GetScratchPixmapHeader 0.00 94.79 __libc_start_main 0.00 94.79 FindAllClientResources 0.00 94.79 FreeFontPath 0.00 94.79 SProcRenderCreateConicalGradient 0.00 94.56 ProcRenderTrapezoids 0.00 94.56 AllocatePicture 0.00 94.56 __glXDispatch 0.00 0.16 __glXVendorPrivate 0.00 0.08 __glXRender 0.00 0.08 SmartScheduleStartTimer 0.00 0.08 [./sysprof] 0.00 2.76 [sshd: ssp@pts/0] 0.00 2.37 [compiz] 0.00 0.08 What's going on here is that the computed load address for the X server binary is different for the debug binary. The lowest allocated address is 0x08047134 for the normal, and 0x8048134 for the debug. But it looks like the addresses are still the same for the symbols. The root of this problem may be that we should ignore the load address of the debug binary, and just lookup the address computed. The *text* segments have the same address though. Everything from "gnu version" on has the same address. So: - find out where in memory the text segment is - take an address and compute its offset to the text segment - in elf parser, find address of text segment - add offset - lookup resulting address So basically, "load address" should really be text address. Except of course that load_address is not used in process.c - instead the 'load address' of the first part of the file is computed and assumed to be equivalent to the load address. So to lookup something you probably actually need to know the load/offset at the elf parser level: lookup_symbol (elf, map, offset, address) then, real load address of text (lta) = map - offset + text_offset offset of called func (ocf): addr - lta thing to lookup in table: ocf + text_addr.loadaddr in debug addr - map - offset + text_offset hmmm ... * plug all the leaks - don't leak the presentation strings/objects - maybe add stack_stash_set_free_func() or something * Delete elf_parser_new() and rename elf_parser_new_from_file() * Add demangling again * Restore filename => binfile cache. * It is apparently possible to get another timer interrupt in the middle of timer_notify. If this happens the circular buffer gets screwed up and you get crashes. Note this gets much worse on SMP (in fact how did this work at all previously?) Possible fixes - have a "in timer notify" variable, then simply reject nested interrupts - keep a "ghost head" that timers can use to allocate new traces, then update the real head whenever one of them completes. Note though, that the traces will get generated in the wrong order due to the nesting. In fact, only the outermost timernotify can update the real head, and it should update it to ghost_head. - do correct locking? Nah, that's crazy talk Also note: a race is a race, and on SMP we probably can't even make it unlikely enough to not matter. Fixed by ignoring the nested interrupts using an atomic variable. * When you load a file from the commandline, there is a weird flash of the toolbar. What's going on is this: - this file is loaded into a tree model - the tree model is set for the function list - this causes the selection changed signal to be emitted - the callback for that signal process updates - somehow in that update process, the toolbar flashes. - turns out to be a gtk+ issue: 350517 - screenshot window must be cleared when you press start. - Formats should become first-class, stand-alone objects that offers help with parsing and nothing else. ParseContext* format_get_parse_context (format, err); gboolean parse_context_begin (parse_context, name, err); gboolean parse_context_end (parse_format, name, err); basically, a Format encapsulates a DFA, and a ParseContext encapsulates the current state. - make stackstash ref counted - Charge 'self' properly to processes that don't get any stack trace at all (probably we get that for free with stackstash reorganisation) - CVS head now has two radio buttons in the right pane, and caller pane is gone. (This turned out to be a bad idea, because it is often useful to click on ancestors to move up the tree). * Don't build the GUI if gtk+ is not installed * Find out why we sometimes get reports of time spent by [pid 0]. * - Run a.out generated normally with gcc. - Run sysprof - hit profile - Kill a.out - strip a.out - run a.out - hit start - hit profile At this point we should not get any symbols, but we do. There is some sort of bad caching going on. * support more than one reader of the samples properly - Don't generate them if noone cares * Correctness - When the module is unloaded, kill all processes blocking in read - or block unloading until all processes have exited Unfortunately this is basically impossible to do with a /proc file (no open() notification). So, for 1.0 this will have to be a dont-do-that-then. For 1.2, we should do it with a sysfs and kobject instead. - When the module is unloaded, can we somehow *guarantee* that no kernel thread is active? Doesn't look like it; however we can get close by decreasing a ref count just before returning from the module. (There may still be return instructions etc. that will get run). This may not be an issue with the timer based scanning we are using currently. * Find out why we get hangs with rawhide kernels. This only happens with the 'trace "current"' code. See this mail: http://mail.nl.linux.org/kernelnewbies/2005-08/msg00157.html esp0 points to top of kernel stack esp points to top of user stack (Reported by Kjartan Maraas). - When not profiling, sysprof shouldn't keep the file open. - Make things faster - Can I get it to profile itself? - speedprof seems to report that lots of time is spent in stack_stash_foreach() and also in generate_key() - add an 'everything' object. It is really needed for a lot of things - should be easy to do with stackstash reorganization. * Handle time being set back in the RESET_DEAD_PERIOD code. - total should probably be cached so that compute_total() doesn't take 80% of the time to generate a profile. - Fixing the oops in kernels < 2.6.11 - Probably just require 2.6.11 (necessary for timer interrupt based anyway). - Make the process waiting in poll() responsible for extracting the backtrace. Give a copy of the entire stack rather than doing the walk inside the kernel. New model: - Two arrays, one of actual scanned stacks one of tasks that need to be scanned One wait queue, wait for data - in read() wait for stack data: scan_tasks() if (!stack_data) return -EWOULDBLOCK; in poll() while (!stack data) { wait_for_data(); scan_tasks(); } return READABLE; scan_tasks() is a function that converts waiting tasks into data, and wakes them up. - in timer interrupt: if (someone waiting in poll() && current && current != that_someone && current is runnable) { stop current; add current to queue; wake wait_for_data; } This way, we will have a real userspace process that can take the page faults. - Different approach: pollable file where a regular userspace process can read a pid. Any pid returned is guaranteed to be UNINTERRUPTIBLE. Userspace process is required to start it again when it is done with it. Also provide interface to read arbitrary memory of that process. ptrace() could in principle do all this, but unfortunately it sucks to continuously ptrace() processes. - Yet another Userspace process can register itself as "profiler" and pass in a filedescriptor where all sorts of information is sent. - could tie lifetime of module to profiler - could send "module going away" information - Can we map filedescriptors to files in a module? * Make sure sysprof-text is not linked to gtk+ * Consider renaming profiler.[ch] to collector.[ch] * Crash reported by Rudi Chiarito with n_addrs == 0. * Find out what distributions it actually works on (ask for sucess/failure-stories in 1.0 releases) * Add note in README about Ubuntu and Debian -dbg packages and how to get debug symbols for X there. stackstash reorg: - make loading and saving work again. - make stashes loadable and savable. - add a way to convert 1.0 files to stashes - Get rid of remaining uses of stack_stash_foreach(), then rename stack_stash_foreach_reversed() to stack_stash_foreach() - stackstash should just take traces of addresses without knowing anything about what those addresses mean. - stacktraces should then begin with a process - stackstash should be extended so that the "create_descendant" and "create_ancestor" code in profile.c can use it directly. At that point, get rid of the profile tree, and rename profile.c to analyze.c. - the profile tree will then just be a stackstash where the addresses are presentation strings instead. - Doing a profile will then amount to converting the raw stash to one where the addresses have been looked up and converted to presentation strings. -=-= - profile should take traces of pointers to presentation objects without knowing anything about these presentation objects. - For each stack node, compute a presentation object (probably need to export opaque stacknode objects with set/get_user_data) - Send each stack trace to the profile module, along with presentation objects. Maybe just a map from stack nodes to presentation objects. - Make the Profile class use the stash directly instead of building its own copy. - store a stash in the profile class - make sure descendants and callers can be built from it. - get rid of other stuff in the profile struct * Before 1.0: - Update version numbers in source - Make tarball - Check that tarball works - cvs commit - cvs tag sysprof-1-0 - Update website - Announce on Freshmeat - Announce on gnome-announce - Announce on kernel list. - Announce on Gnomefiles - Announce on news.gnome.org - Send to slashdot/developers - Announce on devtools list (?) - Announce on Advogato link to archive * The handling of the global variable in signal-handler.[ch] needs to be atomic - right now it isn't. The issue is what happens if a handled signal arrives while we are manipulating the list? * (User space stack must probably be done in a thread - kernel stack must probably be taken in the interrupt itself? - Why this difference? The page tables should still be loaded. Is it because pages_present() doesn't work? No, turning it off doesn't help. - It looks like this works. Get: struct pt_regs *user_regs = (void *)current->thread.esp0 - sizeof (struct pt_regs); then use pages_present as usual to trace with user_regs; There could be rare lockups though. * Non-GUI version that can save in a format the GUI can understand. Could be used for profiling startup etc. Would preferably be able to dump the data to a network socket. Should be able to react to eg. SIGUSR1 by dumping the data. Work done by Lorenzo: http://www.colitti.com/lorenzo/software/gnome-startup/sysprof-text.diff http://www.colitti.com/lorenzo/software/gnome-startup/sysprof.log http://colitti.com/lorenzo/software/gnome-startup/ * consider caching [filename => bin_file] * Check the kernel we are building against, if it is SMP or less than 2.6.11, print a warning and suggest upgrading. * Timer interrupt based * Interface - Consider expanding a few more levels of a new descendants tree - Algorithm should be expand in proportion to the "total" percentage. Basically consider 'total' the likelyhood that the user is going to look at it. - Maybe just; keep expanding the biggest total until there is no more room or we run out of things to expand. * Web page containing - Screen shots - Explanation of what it is - Download - Bug reporting - Contact info - Ask for sucess/failure reports - hook up menu items view/start etc (or possibly get rid of them or move them) - Should do as suggested in the automake manual in the chapter "when automake is not enough" - add an "insert-module" target - need to run depmod on install - If the current profile has a name, display it in the title bar - auto*? - Find out if that PREFIX business in Makefile was really such a great idea. - Sould just install the kernel module if it running as root, pop up a dialog if not. Note we must be able to start without module now, since it is useful to just load profiles from disk. - Is there a portable way of asking for the root password? - Install a small suid program that only inserts the module? (instant security hole ..) - Need to make "make install" work (how do you know where to install kernel modules?) - in /lib/modules/`uname -r`/kernel/drivers/ - need to run depmod as root after that - Then modprobe run as root should correctly find it. - grep FIXME - give profiles on the command line - Hopefully the oops at the end of this file is gone now that we use mmput/get_task_mm. For older kernels those symbols are not exported though, so we will probably have to either use the old way (directly accessing the mm's) or just not support those kernels. - Need an icon - hook up about box - Add busy cursors, - when you hit "Profile" - when you click something in the main list and we don't respond within 50ms (or perhaps when we expect to not be able to do so (can we know the size in advance?)) - kernel module should put process to sleep before sampling. Should get us more accurate data - Make sure samples label shows correct nunber after Open - Move "samples" label to the toolbar, then get rid of statusbar. - crashes when you ctrl-click the selected item in the top left pane ssp: looks like it doesn't handle the none-selected case - loading and saving - consider making ProfileObject more of an object. - make an "everything" object maybe not necessary -- there is a libc_ctors_something() - make presentation strings nicer four different kinds of symbols: a) I know exactly what this is b) I know in what library this is c) I know only the process that did this d) I know the name, but there is another similarly named one (a) is easy, (b) should be (c) should just become "???" (d) not sure - processes with a cmdline of "" should get a [pid = %d] instead. - make an "n samples" label Process stuff: - make threads be reported together (simply report pids with similar command lines together) (note: it seems separating by pid is way too slow (uses too much memory), so it has to be like this) - stack stash should allow different pids to refer to the same root (ie. there is no need to create a new tree for each pid) The *leaves* should contain the pid, not the root. You could even imagine a set of processes, each referring to a set of leaves. - when we see a new pid, immediately capture its mappings Road map: - new object Process - hashable by pointer - contains list of maps - process_from_pid (pid_t pid, gboolean join_threads) - new processes are gets their maps immediately - resulting pointer must be unref()ed, but it is possible it just points to an existing process - processes with identical cmdlines are taken together - method lookup_symbol() - method get_name() - ref/unref - StackStash stores map from process to leaves - Profile is called with processes It is possible that we simply need a better concept of Process: If two pids have the same command line, consider them the same, period. This should save considerable amounts of memory. The assumptions: "No pids are reused during a profiling run" "Two processes with the same command line have the same mappings" are somewhat dubious, but probably necessary. (More complex kernel: have the module report - new pid arrived (along with mappings) - mapping changed for pid - stacktrace) - make symbols in executable work - the hashtables used in profile.c should not accept NULL as the key - make callers work - autoexpand descendant tree - make double clicks work - fix leaks - Find out what happened here: Apr 11 15:42:08 great-sage-equal-to-heaven kernel: Unable to handle kernel NULL pointer dereference at virtual address 000001b8 Apr 11 15:42:08 great-sage-equal-to-heaven kernel: printing eip: Apr 11 15:42:08 great-sage-equal-to-heaven kernel: c017342c Apr 11 15:42:08 great-sage-equal-to-heaven kernel: *pde = 00000000 Apr 11 15:42:08 great-sage-equal-to-heaven kernel: Oops: 0000 [#1] Apr 11 15:42:08 great-sage-equal-to-heaven kernel: Modules linked in: sysprof_module(U) i2c_algo_bit md5 ipv6 parport_pc lp parport autofs4 sunrpc video button battery ac ohci1394 ieee1394 uhci_hcd ehci_hcd hw_random tpm_atmel tpm i2c_i801 i2c_core snd_intel8x0 snd_ac97_codec snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd soundcore snd_page_alloc e1000 floppy dm_snapshot dm_zero dm_mirror ext3 jbd dm_mod ata_piix libata sd_mod scsi_mod Apr 11 15:42:08 great-sage-equal-to-heaven kernel: CPU: 0 Apr 11 15:42:08 great-sage-equal-to-heaven kernel: EIP: 0060:[] Not tainted VLI Apr 11 15:42:08 great-sage-equal-to-heaven kernel: EFLAGS: 00010287 (2.6.11-1.1225_FC4) Apr 11 15:42:08 great-sage-equal-to-heaven kernel: EIP is at grab_swap_token+0x35/0x21f Apr 11 15:42:08 great-sage-equal-to-heaven kernel: eax: 0bd48023 ebx: d831d028 ecx: 00000282 edx: 00000000 Apr 11 15:42:08 great-sage-equal-to-heaven kernel: esi: c1b72934 edi: c1045820 ebp: c1b703f0 esp: c18dbdd8 Apr 11 15:42:08 great-sage-equal-to-heaven kernel: ds: 007b es: 007b ss: 0068 Apr 11 15:42:08 great-sage-equal-to-heaven kernel: Process events/0 (pid: 3, threadinfo=c18db000 task=f7e62000) Apr 11 15:42:09 great-sage-equal-to-heaven kernel: Stack: 000011a8 00000000 000011a8 c1b703f0 c0151731 c016f58f 000011a8 c1b72934 Apr 11 15:42:09 great-sage-equal-to-heaven kernel: 000011a8 c0166415 c1b72934 c1b72934 c0163768 ee7ccc38 f459fbf8 bf92e7b8 Apr 11 15:42:09 great-sage-equal-to-heaven kernel: f6c6a934 c0103b92 bfdaba18 c1b703f0 00000001 c1b81bfc c1b72934 bfdaba18 Apr 11 15:42:09 great-sage-equal-to-heaven kernel: Call Trace: Apr 11 15:42:09 great-sage-equal-to-heaven kernel: [] find_get_page+0x9/0x24 Apr 11 15:42:09 great-sage-equal-to-heaven kernel: [] read_swap_cache_async+0x32/0x83Apr 11 15:42:09 great-sage-equal-to-heaven kernel: [] do_swap_page+0x262/0x600 Apr 11 15:42:09 great-sage-equal-to-heaven kernel: [] pte_alloc_map+0xc6/0x1e6 Apr 11 15:42:09 great-sage-equal-to-heaven kernel: [] common_interrupt+0x1a/0x20 Apr 11 15:42:09 great-sage-equal-to-heaven kernel: [] handle_mm_fault+0x1da/0x31d Apr 11 15:42:09 great-sage-equal-to-heaven kernel: [] __follow_page+0xa2/0x10d Apr 11 15:42:09 great-sage-equal-to-heaven kernel: [] get_user_pages+0x145/0x6ee Apr 11 15:42:09 great-sage-equal-to-heaven kernel: [] kmap_high+0x52/0x44e Apr 11 15:42:09 great-sage-equal-to-heaven kernel: [] common_interrupt+0x1a/0x20 Apr 11 15:42:09 great-sage-equal-to-heaven kernel: [] x_access_process_vm+0x111/0x1a5 [sysprof_module] Apr 11 15:42:10 great-sage-equal-to-heaven kernel: [] read_user_space+0x19/0x1d [sysprof_module] Apr 11 15:42:10 great-sage-equal-to-heaven kernel: [] read_frame+0x35/0x51 [sysprof_module] Apr 11 15:42:10 great-sage-equal-to-heaven kernel: [] generate_stack_trace+0x8b/0xb4 Apr 11 15:42:10 great-sage-equal-to-heaven kernel: [] do_generate+0x3f/0xa0 [sysprof_module] Apr 11 15:42:10 great-sage-equal-to-heaven kernel: [] worker_thread+0x1b0/0x450 Apr 11 15:42:10 great-sage-equal-to-heaven kernel: [] schedule+0x30d/0x780 Apr 11 15:42:10 great-sage-equal-to-heaven kernel: [] __wake_up_common+0x39/0x59 Apr 11 15:42:10 great-sage-equal-to-heaven kernel: [] do_generate+0x0/0xa0 [sysprof_module] Apr 11 15:42:10 great-sage-equal-to-heaven kernel: [] default_wake_function+0x0/0xc Apr 11 15:42:10 great-sage-equal-to-heaven kernel: [] worker_thread+0x0/0x450 Apr 11 15:42:10 great-sage-equal-to-heaven kernel: [] kthread+0x87/0x8b Apr 11 15:42:10 great-sage-equal-to-heaven kernel: [] kthread+0x0/0x8b Apr 11 15:42:10 great-sage-equal-to-heaven kernel: [] kernel_thread_helper+0x5/0xb Apr 11 15:42:10 great-sage-equal-to-heaven kernel: Code: e0 8b 00 8b 50 74 8b 1d c4 55 3d c0 39 da 0f 84 9b 01 00 00 a1 60 fc 3c c0 39 05 30 ec 48 c0 78 05 83 c4 20 5b c3 a1 60 fc 3c c0 <3b> 82 b8 01 00 00 78 ee 81 3d ac 55 3d c0 3c 4b 24 1d 0f 85 78 sysprof-1.2.0/60-sysprof.rules0000644000175000017500000000006712021176713013147 00000000000000KERNEL=="sysprof-trace", MODE="0644" sysprof-1.2.0/watch.c0000644000175000017500000001664512021176713011426 00000000000000/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- */ /* - Library for asynchronous communication * Copyright (C) 2002 Sren Sandmann (sandmann@daimi.au.dk) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "watch.h" typedef struct Watch Watch; struct Watch { GSource source; GPollFD poll_fd; gboolean removed; WatchCallback read_callback; WatchCallback write_callback; WatchCallback hangup_callback; WatchCallback error_callback; WatchCallback priority_callback; gpointer data; }; static GHashTable *watched_fds; static void init (void) { if (!watched_fds) watched_fds = g_hash_table_new (g_int_hash, g_int_equal); } static Watch * lookup_watch (gint fd) { init (); return g_hash_table_lookup (watched_fds, &fd); } static void internal_add_watch (Watch *watch) { gpointer fd = &(watch->poll_fd.fd); init (); g_hash_table_insert (watched_fds, fd, watch); g_source_add_poll ((GSource *)watch, &(watch->poll_fd)); } static void internal_remove_watch (Watch *watch) { gpointer fd = &(watch->poll_fd.fd); init (); watch->removed = TRUE; g_source_remove_poll ((GSource *)watch, &(watch->poll_fd)); g_hash_table_remove (watched_fds, fd); } static gboolean watch_prepare (GSource *source, gint *timeout) { *timeout = -1; return FALSE; } static gboolean watch_check (GSource *source) { Watch *watch = (Watch *)source; gint revents = watch->poll_fd.revents; if (revents & (G_IO_NVAL)) { /* This can happen if the user closes the file descriptor * without first removing the watch. We silently ignore it */ internal_remove_watch (watch); g_source_unref (source); return FALSE; } if ((revents & G_IO_HUP) && watch->hangup_callback) return TRUE; if ((revents & G_IO_IN) && watch->read_callback) return TRUE; if ((revents & G_IO_PRI) && watch->priority_callback) return TRUE; if ((revents & G_IO_ERR) && watch->error_callback) return TRUE; if ((revents & G_IO_OUT) && watch->write_callback) return TRUE; return FALSE; } static gboolean watch_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) { Watch *watch = (Watch *)source; gint revents = watch->poll_fd.revents; gboolean removed; g_source_ref (source); if (!watch->removed && (revents & G_IO_IN) && watch->read_callback) watch->read_callback (watch->data); if (!watch->removed && (revents & G_IO_PRI) && watch->priority_callback) watch->priority_callback (watch->data); if (!watch->removed && (revents & G_IO_OUT) && watch->write_callback) watch->write_callback (watch->data); if (!watch->removed && (revents & G_IO_ERR) && watch->error_callback) watch->error_callback (watch->data); if (!watch->removed && (revents & G_IO_HUP) && watch->hangup_callback) watch->hangup_callback (watch->data); removed = watch->removed; g_source_unref (source); if (removed) return FALSE; return TRUE; } static void watch_finalize (GSource *source) { } static void update_poll_mask (Watch *watch) { gint events = 0; g_source_remove_poll ((GSource *)watch, &(watch->poll_fd)); if (watch->read_callback) events |= G_IO_IN; if (watch->write_callback) events |= G_IO_OUT; if (watch->priority_callback) events |= G_IO_PRI; if (watch->hangup_callback) events |= G_IO_HUP; if (watch->error_callback) events |= G_IO_ERR; watch->poll_fd.events = events; g_source_add_poll ((GSource *)watch, &(watch->poll_fd)); } void fd_add_watch (gint fd, gpointer data) { static GSourceFuncs watch_funcs = { watch_prepare, watch_check, watch_dispatch, watch_finalize, }; Watch *watch = lookup_watch (fd); g_return_if_fail (fd > 0); g_return_if_fail (watch == NULL); watch = (Watch *)g_source_new (&watch_funcs, sizeof (Watch)); g_source_set_can_recurse ((GSource *)watch, TRUE); g_source_attach ((GSource *)watch, NULL); watch->poll_fd.fd = fd; watch->poll_fd.events = 0; watch->removed = FALSE; watch->read_callback = NULL; watch->write_callback = NULL; watch->hangup_callback = NULL; watch->error_callback = NULL; watch->priority_callback = NULL; watch->data = data; internal_add_watch (watch); } void fd_set_read_callback (gint fd, WatchCallback read_cb) { Watch *watch = lookup_watch (fd); g_return_if_fail (fd > 0); g_return_if_fail (watch != NULL); if (watch->read_callback != read_cb) { watch->read_callback = read_cb; update_poll_mask (watch); } } void fd_set_write_callback (gint fd, WatchCallback write_cb) { Watch *watch = lookup_watch (fd); g_return_if_fail (fd > 0); g_return_if_fail (watch != NULL); if (watch->write_callback != write_cb) { watch->write_callback = write_cb; update_poll_mask (watch); } } void fd_set_hangup_callback (gint fd, WatchCallback hangup_cb) { Watch *watch = lookup_watch (fd); g_return_if_fail (fd > 0); g_return_if_fail (watch != NULL); if (watch->hangup_callback != hangup_cb) { watch->hangup_callback = hangup_cb; update_poll_mask (watch); } } void fd_set_error_callback (gint fd, WatchCallback error_cb) { Watch *watch = lookup_watch (fd); g_return_if_fail (fd > 0); g_return_if_fail (watch != NULL); if (watch->error_callback != error_cb) { watch->error_callback = error_cb; update_poll_mask (watch); } } void fd_set_priority_callback (gint fd, WatchCallback priority_cb) { Watch *watch = lookup_watch (fd); g_return_if_fail (fd > 0); g_return_if_fail (watch != NULL); if (watch->priority_callback != priority_cb) { watch->priority_callback = priority_cb; update_poll_mask (watch); } } void fd_remove_watch (gint fd) { Watch *watch = lookup_watch (fd); g_return_if_fail (fd > 0); if (!watch) return; internal_remove_watch (watch); g_source_unref ((GSource *)watch); } gboolean fd_is_watched (gint fd) { g_return_val_if_fail (fd > 0, FALSE); if (lookup_watch (fd)) return TRUE; else return FALSE; } sysprof-1.2.0/profile.c0000644000175000017500000003420112021176713011744 00000000000000/* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, Red Hat, Inc. * Copyright 2004, 2005, 2006, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "binfile.h" #include "stackstash.h" #include "profile.h" #include "sfile.h" struct Profile { StackStash *stash; }; static SFormat * create_format (void) { SFormat *format; SForward *object_forward; SForward *node_forward; format = sformat_new(); object_forward = sformat_declare_forward (format); node_forward = sformat_declare_forward (format); sformat_set_type ( format, sformat_make_record ( format, "profile", NULL, sformat_make_integer (format, "size"), sformat_make_pointer (format, "call_tree", node_forward), sformat_make_list ( format, "objects", NULL, sformat_make_record ( format, "object", object_forward, sformat_make_string (format, "name"), sformat_make_integer (format, "total"), sformat_make_integer (format, "self"), NULL)), sformat_make_list ( format, "nodes", NULL, sformat_make_record ( format, "node", node_forward, sformat_make_pointer (format, "object", object_forward), sformat_make_pointer (format, "siblings", node_forward), sformat_make_pointer (format, "children", node_forward), sformat_make_pointer (format, "parent", node_forward), sformat_make_integer (format, "total"), sformat_make_integer (format, "self"), sformat_make_integer (format, "toplevel"), NULL)), NULL)); return format; } static void serialize_call_tree (StackNode *node, SFileOutput *output) { if (!node) return; sfile_begin_add_record (output, "node"); sfile_add_pointer (output, "object", U64_TO_POINTER (node->data)); sfile_add_pointer (output, "siblings", node->siblings); sfile_add_pointer (output, "children", node->children); sfile_add_pointer (output, "parent", node->parent); sfile_add_integer (output, "total", node->total); sfile_add_integer (output, "self", node->size); sfile_add_integer (output, "toplevel", node->toplevel); sfile_end_add (output, "node", node); serialize_call_tree (node->siblings, output); serialize_call_tree (node->children, output); } gboolean profile_save (Profile *profile, const char *file_name, GError **err) { gboolean result; GList *profile_objects; GList *list; SFormat *format = create_format (); SFileOutput *output = sfile_output_new (format); sfile_begin_add_record (output, "profile"); sfile_add_integer (output, "size", profile_get_size (profile)); sfile_add_pointer (output, "call_tree", stack_stash_get_root (profile->stash)); profile_objects = profile_get_objects (profile); sfile_begin_add_list (output, "objects"); for (list = profile_objects; list != NULL; list = list->next) { ProfileObject *object = list->data; sfile_begin_add_record (output, "object"); sfile_add_string (output, "name", object->name); sfile_add_integer (output, "total", object->total); sfile_add_integer (output, "self", object->self); sfile_end_add (output, "object", object->name); } g_list_foreach (profile_objects, (GFunc)g_free, NULL); g_list_free (profile_objects); sfile_end_add (output, "objects", NULL); sfile_begin_add_list (output, "nodes"); serialize_call_tree (stack_stash_get_root (profile->stash), output); sfile_end_add (output, "nodes", NULL); sfile_end_add (output, "profile", NULL); result = sfile_output_save (output, file_name, err); sfile_output_free (output); sformat_free (format); return result; } Profile * profile_load (const char *filename, GError **err) { SFormat *format; SFileInput *input; Profile *profile; int n, i; StackNode *root; format = create_format (); input = sfile_load (filename, format, err); if (!input) return NULL; profile = g_new (Profile, 1); sfile_begin_get_record (input, "profile"); sfile_get_integer (input, "size", NULL); sfile_get_pointer (input, "call_tree", (gpointer *)&root); n = sfile_begin_get_list (input, "objects"); for (i = 0; i < n; ++i) { char *string; sfile_begin_get_record (input, "object"); sfile_get_string (input, "name", &string); sfile_get_integer (input, "total", NULL); sfile_get_integer (input, "self", NULL); sfile_end_get (input, "object", string); } sfile_end_get (input, "objects", NULL); profile->stash = stack_stash_new ((GDestroyNotify)g_free); n = sfile_begin_get_list (input, "nodes"); for (i = 0; i < n; ++i) { StackNode *node = stack_node_new (profile->stash); gint32 size; gint32 total; sfile_begin_get_record (input, "node"); sfile_get_pointer (input, "object", (gpointer *)&node->data); sfile_get_pointer (input, "siblings", (gpointer *)&node->siblings); sfile_get_pointer (input, "children", (gpointer *)&node->children); sfile_get_pointer (input, "parent", (gpointer *)&node->parent); sfile_get_integer (input, "total", &total); sfile_get_integer (input, "self", (gint32 *)&size); sfile_get_integer (input, "toplevel", NULL); node->total = total; node->size = size; sfile_end_get (input, "node", node); g_assert (node->siblings != (void *)0x11); } sfile_end_get (input, "nodes", NULL); sfile_end_get (input, "profile", NULL); sfile_input_free (input); sformat_free (format); stack_stash_set_root (profile->stash, root); return profile; } Profile * profile_new (StackStash *stash) { Profile *profile = g_new (Profile, 1); profile->stash = stack_stash_ref (stash); return profile; } static void add_trace_to_tree (StackLink *trace, gint size, gpointer data) { StackLink *link; ProfileDescendant *parent = NULL; ProfileDescendant **tree = data; link = trace; while (link->next) link = link->next; for (; link != NULL; link = link->prev) { gpointer address = U64_TO_POINTER (link->data); ProfileDescendant *prev = NULL; ProfileDescendant *match = NULL; for (match = *tree; match != NULL; prev = match, match = match->siblings) { if (match->name == address) { if (prev) { /* Move to front */ prev->siblings = match->siblings; match->siblings = *tree; *tree = match; } break; } } if (!match) { /* Have we seen this object further up the tree? */ for (match = parent; match != NULL; match = match->parent) { if (match->name == address) break; } } if (!match) { match = g_new (ProfileDescendant, 1); match->name = address; match->cumulative = 0; match->self = 0; match->children = NULL; match->parent = parent; match->siblings = *tree; *tree = match; } tree = &(match->children); parent = match; } parent->self += size; while (parent) { parent->cumulative += size; parent = parent->parent; } } ProfileDescendant * profile_create_descendants (Profile *profile, char *object_name) { ProfileDescendant *tree = NULL; StackNode *node = stack_stash_find_node (profile->stash, object_name); while (node) { if (node->toplevel) stack_node_foreach_trace (node, add_trace_to_tree, &tree); node = node->next; } return tree; } static ProfileCaller * profile_caller_new (void) { ProfileCaller *caller = g_new (ProfileCaller, 1); caller->next = NULL; caller->self = 0; caller->total = 0; return caller; } ProfileCaller * profile_list_callers (Profile *profile, char *callee_name) { StackNode *node; StackNode *callees; GHashTable *callers_by_name; GHashTable *processed_callers; ProfileCaller *result = NULL; callers_by_name = g_hash_table_new (g_direct_hash, g_direct_equal); processed_callers = g_hash_table_new (g_direct_hash, g_direct_equal); callees = stack_stash_find_node (profile->stash, callee_name); for (node = callees; node != NULL; node = node->next) { ProfileCaller *caller; if (!node->parent) continue; caller = g_hash_table_lookup ( callers_by_name, U64_TO_POINTER (node->parent->data)); if (!caller) { caller = profile_caller_new (); caller->name = U64_TO_POINTER (node->parent->data); caller->total = 0; caller->self = 0; caller->next = result; result = caller; g_hash_table_insert ( callers_by_name, U64_TO_POINTER (node->parent->data), caller); } } for (node = callees; node != NULL; node = node->next) { StackNode *top_caller = node->parent; StackNode *top_callee = node; StackNode *n; ProfileCaller *caller; if (!node->parent) continue; for (n = node; n && n->parent; n = n->parent) { if (n->data == node->data && n->parent->data == node->parent->data) { top_caller = n->parent; top_callee = n; } } caller = g_hash_table_lookup ( callers_by_name, U64_TO_POINTER (node->parent->data)); if (!g_hash_table_lookup (processed_callers, top_caller)) { caller->total += top_callee->total; g_hash_table_insert (processed_callers, top_caller, top_caller); } caller->self += node->size; } g_hash_table_destroy (processed_callers); g_hash_table_destroy (callers_by_name); return result; } #if 0 /* This code generates a list of all ancestors, rather than * all callers. It turned out to not work well in practice, * but on the other hand the single list of callers is not * all that great either, so we'll keep it around commented * out for now */ static void add_to_list (gpointer key, gpointer value, gpointer user_data) { GList **list = user_data; *list = g_list_prepend (*list, value); } static GList * listify_hash_table (GHashTable *hash_table) { GList *result = NULL; g_hash_table_foreach (hash_table, add_to_list, &result); return result; } ProfileCaller * profile_list_ancestors (Profile *profile, char *callee_name) { StackNode *callees; StackNode *node; GHashTable *callers_by_name; ProfileCaller *result = NULL; callers_by_name = g_hash_table_new (g_direct_hash, g_direct_equal); callees = stack_stash_find_node (profile->stash, callee_name); for (node = callees; node != NULL; node = node->next) { StackNode *n; gboolean seen_recursive_call; GHashTable *total_ancestors; GHashTable *all_ancestors; GList *all, *list; /* Build a list of those ancestors that should get assigned * totals. If this callee does not have any recursive calls * higher up, that means all of it's ancestors. If it does * have a recursive call, only the one between this node * and the recursive call should get assigned total */ seen_recursive_call = FALSE; all_ancestors = g_hash_table_new (g_direct_hash, g_direct_equal); total_ancestors = g_hash_table_new (g_direct_hash, g_direct_equal); for (n = node->parent; n; n = n->parent) { if (!seen_recursive_call) { g_hash_table_insert (total_ancestors, n->address, n); } else { g_hash_table_remove (total_ancestors, n->address); } g_hash_table_insert (all_ancestors, n->address, n); if (n->address == node->address) seen_recursive_call = TRUE; } all = listify_hash_table (all_ancestors); for (list = all; list; list = list->next) { ProfileCaller *caller; StackNode *ancestor = list->data; caller = g_hash_table_lookup (callers_by_name, ancestor->address); if (!caller) { caller = profile_caller_new (); g_hash_table_insert ( callers_by_name, ancestor->address, caller); caller->name = ancestor->address; caller->next = result; result = caller; } caller->self += node->size; if (g_hash_table_lookup (total_ancestors, ancestor->address)) caller->total += node->total; } g_list_free (all); g_hash_table_destroy (all_ancestors); g_hash_table_destroy (total_ancestors); } return result; } #endif void profile_free (Profile *profile) { stack_stash_unref (profile->stash); g_free (profile); } void profile_descendant_free (ProfileDescendant *descendant) { if (!descendant) return; profile_descendant_free (descendant->siblings); profile_descendant_free (descendant->children); g_free (descendant); } void profile_caller_free (ProfileCaller *caller) { if (!caller) return; profile_caller_free (caller->next); g_free (caller); } static int compute_total (StackNode *node) { StackNode *n; int total = 0; for (n = node; n != NULL; n = n->next) { if (n->toplevel) total += n->total; } return total; } static void build_object_list (StackNode *node, gpointer data) { GList **objects = data; ProfileObject *obj; StackNode *n; obj = g_new (ProfileObject, 1); obj->name = U64_TO_POINTER (node->data); obj->total = compute_total (node); obj->self = 0; for (n = node; n != NULL; n = n->next) obj->self += n->size; *objects = g_list_prepend (*objects, obj); } GList * profile_get_objects (Profile *profile) { GList *objects = NULL; stack_stash_foreach_by_address ( profile->stash, build_object_list, &objects); return objects; } gint profile_get_size (Profile *profile) { StackNode *n; gint size = 0; for (n = stack_stash_get_root (profile->stash); n != NULL; n = n->siblings) size += n->total; return size; } sysprof-1.2.0/collector.c0000644000175000017500000004172612021207650012277 00000000000000/* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, Red Hat, Inc. * Copyright 2004, 2005, Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include "stackstash.h" #include "collector.h" #include "watch.h" #include "elfparser.h" #include "tracker.h" #include #include "util.h" #define d_print(...) #define N_PAGES 32 /* Number of pages in the ringbuffer */ #define N_WAKEUP_EVENTS 149 typedef struct counter_t counter_t; typedef struct sample_event_t sample_event_t; typedef struct mmap_event_t mmap_event_t; typedef struct comm_event_t comm_event_t; typedef struct exit_event_t exit_event_t; typedef struct fork_event_t fork_event_t; typedef union counter_event_t counter_event_t; static void process_event (Collector *collector, counter_t *counter, counter_event_t *event); struct counter_t { Collector * collector; int fd; struct perf_event_mmap_page * mmap_page; uint8_t * data; uint64_t tail; int cpu; }; struct sample_event_t { struct perf_event_header header; uint64_t ip; uint32_t pid, tid; uint64_t n_ips; uint64_t ips[1]; }; struct comm_event_t { struct perf_event_header header; uint32_t pid, tid; char comm[1]; }; struct mmap_event_t { struct perf_event_header header; uint32_t pid, tid; uint64_t addr; uint64_t len; uint64_t pgoff; char filename[1]; }; struct fork_event_t { struct perf_event_header header; uint32_t pid, ppid; uint32_t tid, ptid; }; struct exit_event_t { struct perf_event_header header; uint32_t pid, ppid; uint32_t tid, ptid; }; union counter_event_t { struct perf_event_header header; mmap_event_t mmap; comm_event_t comm; sample_event_t sample; fork_event_t fork; exit_event_t exit; }; struct Collector { CollectorFunc callback; gpointer data; tracker_t * tracker; GTimeVal latest_reset; int prev_samples; int n_samples; GList * counters; gboolean use_hw_counters; }; static int get_n_cpus (void) { return sysconf (_SC_NPROCESSORS_ONLN); } static int sysprof_perf_counter_open (struct perf_event_attr *attr, pid_t pid, int cpu, int group_fd, unsigned long flags) { #ifndef __NR_perf_counter_open #if defined(__i386__) #define __NR_perf_counter_open 336 #elif defined(__x86_64__) #define __NR_perf_counter_open 298 #elif defined(__arm__) #define __NR_perf_counter_open 364 #elif defined(__bfin__) #define __NR_perf_counter_open 369 #elif defined(__frv__) #define __NR_perf_counter_open 336 #elif defined(__m68k__) #define __NR_perf_counter_open 332 #elif defined(__MICROBLAZE__) #define __NR_perf_counter_open 366 #elif defined(__mips__) && defined(_ABIO32) #define __NR_perf_counter_open 4333 #elif defined(__mips__) && defined(_ABIN32) #define __NR_perf_counter_open 6296 #elif defined(__mips__) && defined(_ABI64) #define __NR_perf_counter_open 5292 #elif defined(__mn10300__) #define __NR_perf_counter_open 337 #elif defined(__hppa__) #define __NR_perf_counter_open 318 #elif defined(__powerpc__) || defined(__powerpc64__) #define __NR_perf_counter_open 319 #elif defined(__s390__) #define __NR_perf_counter_open 331 #elif defined(__sh__) && (!defined(__SH5__) || __SH5__ == 32) #define __NR_perf_counter_open 336 #elif defined(__sh__) && defined(__SH5__) && __SH5__ == 64 #define __NR_perf_counter_open 364 #elif defined(__sparc__) || defined(__sparc64__) #define __NR_perf_counter_open 327 #endif #endif attr->size = sizeof(*attr); return syscall (__NR_perf_counter_open, attr, pid, cpu, group_fd, flags); } static double timeval_to_ms (const GTimeVal *timeval) { return (timeval->tv_sec * G_USEC_PER_SEC + timeval->tv_usec) / 1000.0; } static double time_diff (const GTimeVal *first, const GTimeVal *second) { double first_ms = timeval_to_ms (first); double second_ms = timeval_to_ms (second); return first_ms - second_ms; } #define RESET_DEAD_PERIOD 250 static gboolean in_dead_period (Collector *collector) { GTimeVal now; double diff; g_get_current_time (&now); diff = time_diff (&now, &collector->latest_reset); if (diff >= 0.0 && diff < RESET_DEAD_PERIOD) return TRUE; return FALSE; } static int get_page_size (void) { static int page_size; static gboolean has_page_size = FALSE; if (!has_page_size) { page_size = getpagesize(); has_page_size = TRUE; } return page_size; } static void on_read (gpointer data) { counter_t *counter = data; int mask = (N_PAGES * get_page_size() - 1); int n_bytes = mask + 1; gboolean skip_samples; Collector *collector; uint64_t head, tail; collector = counter->collector; tail = counter->tail; head = counter->mmap_page->data_head; rmb(); if (head < tail) { g_warning ("sysprof fails at ring buffers (head "FMT64", tail "FMT64"\n", head, tail); tail = head; } #if 0 /* Verify that the double mapping works */ x = g_random_int() & mask; g_assert (*(counter->data + x) == *(counter->data + x + n_bytes)); #endif skip_samples = in_dead_period (collector); #if 0 g_print ("n bytes %d\n", head - tail); #endif while (head - tail >= sizeof (struct perf_event_header)) { struct perf_event_header *header; guint8 buffer[4096]; guint8 *free_me; free_me = NULL; /* Note that: * * - perf events are a multiple of 64 bits * - the perf event header is 64 bits * - the data area is a multiple of 64 bits * * which means there will always be space for one header, which means we * can safely dereference the size field. */ header = (struct perf_event_header *)(counter->data + (tail & mask)); if (header->size > head - tail) { /* The kernel did not generate a complete event. * I don't think that can happen, but we may as well * be paranoid. */ break; } if (counter->data + (tail & mask) + header->size > counter->data + n_bytes) { int n_before, n_after; guint8 *b; if (header->size > sizeof (buffer)) free_me = b = g_malloc (header->size); else b = buffer; n_after = (tail & mask) + header->size - n_bytes; n_before = header->size - n_after; memcpy (b, counter->data + (tail & mask), n_before); memcpy (b + n_before, counter->data, n_after); header = (struct perf_event_header *)b; } if (!skip_samples || header->type != PERF_RECORD_SAMPLE) { if (header->type == PERF_RECORD_SAMPLE) collector->n_samples++; process_event (collector, counter, (counter_event_t *)header); } if (free_me) g_free (free_me); tail += header->size; } counter->tail = tail; counter->mmap_page->data_tail = tail; if (collector->callback) { if (collector->n_samples - collector->prev_samples >= N_WAKEUP_EVENTS) { gboolean first_sample = collector->prev_samples == 0; collector->callback (first_sample, collector->data); collector->prev_samples = collector->n_samples; } } } static void * fail (GError **err, const char *what) { g_set_error (err, COLLECTOR_ERROR, COLLECTOR_ERROR_FAILED, "%s: %s", what, g_strerror (errno)); return NULL; } static void * map_buffer (counter_t *counter, GError **err) { int n_bytes = N_PAGES * get_page_size(); void *address; address = mmap (NULL, n_bytes + get_page_size(), PROT_READ | PROT_WRITE, MAP_SHARED, counter->fd, 0); if (address == MAP_FAILED) return fail (err, "mmap"); return address; } static gboolean counter_set_output (counter_t *counter, int output) { return ioctl (counter->fd, PERF_EVENT_IOC_SET_OUTPUT, output) == 0; } static void counter_enable (counter_t *counter) { ioctl (counter->fd, PERF_EVENT_IOC_ENABLE); } static void counter_disable (counter_t *counter) { d_print ("disable\n"); ioctl (counter->fd, PERF_EVENT_IOC_DISABLE); } static counter_t * counter_new (Collector *collector, pid_t pid, int cpu, counter_t *output, GError **err) { struct perf_event_attr attr; counter_t *counter; int fd; counter = g_new (counter_t, 1); memset (&attr, 0, sizeof (attr)); attr.type = PERF_TYPE_HARDWARE; attr.config = PERF_COUNT_HW_CPU_CYCLES; attr.sample_period = 1200000 ; /* In number of clock cycles - * FIXME: consider using frequency instead */ attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_CALLCHAIN; attr.wakeup_events = N_WAKEUP_EVENTS; attr.disabled = TRUE; attr.mmap = 1; attr.comm = 1; attr.task = 1; attr.exclude_idle = 1; if (!collector->use_hw_counters || (fd = sysprof_perf_counter_open (&attr, pid, cpu, -1, 0)) < 0) { attr.type = PERF_TYPE_SOFTWARE; attr.config = PERF_COUNT_SW_CPU_CLOCK; attr.sample_period = 1000000; fd = sysprof_perf_counter_open (&attr, pid, cpu, -1, 0); } if (fd < 0) return fail (err, "Could not open performance counter"); counter->collector = collector; counter->fd = fd; counter->cpu = cpu; if (output && counter_set_output (counter, output->fd)) { counter->mmap_page = NULL; counter->data = NULL; counter->tail = 0; } else { counter->mmap_page = map_buffer (counter, err); if (!counter->mmap_page || counter->mmap_page == MAP_FAILED) return NULL; counter->data = (uint8_t *)counter->mmap_page + get_page_size (); counter->tail = 0; fd_add_watch (fd, counter); fd_set_read_callback (fd, on_read); } return counter; } static void counter_free (counter_t *counter) { d_print ("munmap\n"); munmap (counter->mmap_page, (N_PAGES + 1) * get_page_size()); fd_remove_watch (counter->fd); close (counter->fd); g_free (counter); } /* * Collector */ static void enable_counters (Collector *collector) { GList *list; d_print ("enable\n"); for (list = collector->counters; list != NULL; list = list->next) { counter_t *counter = list->data; counter_enable (counter); } } static void disable_counters (Collector *collector) { GList *list; d_print ("disable\n"); for (list = collector->counters; list != NULL; list = list->next) { counter_t *counter = list->data; counter_disable (counter); } } void collector_reset (Collector *collector) { /* Disable the counters so that we won't track * the activity of tracker_free()/tracker_new() * * They will still record fork/mmap/etc. so * we can keep an accurate log of process creation */ if (collector->counters) { d_print ("disable counters\n"); disable_counters (collector); } if (collector->tracker) { tracker_free (collector->tracker); collector->tracker = tracker_new (); } collector->n_samples = 0; collector->prev_samples = 0; g_get_current_time (&collector->latest_reset); if (collector->counters) { d_print ("enable counters\n"); enable_counters (collector); } } /* callback is called whenever a new sample arrives */ Collector * collector_new (gboolean use_hw_counters, CollectorFunc callback, gpointer data) { Collector *collector = g_new0 (Collector, 1); collector->callback = callback; collector->data = data; collector->tracker = NULL; collector->use_hw_counters = use_hw_counters; collector_reset (collector); return collector; } static void process_mmap (Collector *collector, mmap_event_t *mmap) { tracker_add_map (collector->tracker, mmap->pid, mmap->addr, mmap->addr + mmap->len, mmap->pgoff, 0, /* inode */ mmap->filename); } static void process_comm (Collector *collector, comm_event_t *comm) { d_print ("pid, tid: %d %d", comm->pid, comm->tid); tracker_add_process (collector->tracker, comm->pid, comm->comm); } static void process_fork (Collector *collector, fork_event_t *fork) { d_print ("ppid: %d pid: %d ptid: %d tid %d\n", fork->ppid, fork->pid, fork->ptid, fork->tid); tracker_add_fork (collector->tracker, fork->ppid, fork->pid); } static void process_exit (Collector *collector, exit_event_t *exit) { d_print ("for %d %d", exit->pid, exit->tid); tracker_add_exit (collector->tracker, exit->pid); } static void process_sample (Collector *collector, sample_event_t *sample) { uint64_t *ips; int n_ips; d_print ("pid, tid: %d %d", sample->pid, sample->tid); if (sample->n_ips == 0) { uint64_t trace[3]; if (sample->header.misc & PERF_RECORD_MISC_KERNEL) { trace[0] = PERF_CONTEXT_KERNEL; trace[1] = sample->ip; trace[2] = PERF_CONTEXT_USER; ips = trace; n_ips = 3; } else { trace[0] = PERF_CONTEXT_USER; trace[1] = sample->ip; ips = trace; n_ips = 2; } } else { ips = sample->ips; n_ips = sample->n_ips; } tracker_add_sample (collector->tracker, sample->pid, ips, n_ips); } static void process_event (Collector *collector, counter_t *counter, counter_event_t *event) { char *name; switch (event->header.type) { case PERF_RECORD_MMAP: name = "mmap"; break; case PERF_RECORD_LOST: name = "lost"; break; case PERF_RECORD_COMM: name = "comm"; break; case PERF_RECORD_EXIT: name = "exit"; break; case PERF_RECORD_THROTTLE: name = "throttle"; break; case PERF_RECORD_UNTHROTTLE: name = "unthrottle"; break; case PERF_RECORD_FORK: name = "fork"; break; case PERF_RECORD_READ: name = "read"; break; case PERF_RECORD_SAMPLE: name = "samp"; break; default: name = "unknown"; break; } d_print ("cpu %d :: %s :: ", counter->cpu, name); switch (event->header.type) { case PERF_RECORD_MMAP: process_mmap (collector, &event->mmap); break; case PERF_RECORD_LOST: g_print ("lost event\n"); break; case PERF_RECORD_COMM: process_comm (collector, &event->comm); break; case PERF_RECORD_EXIT: process_exit (collector, &event->exit); break; case PERF_RECORD_THROTTLE: g_print ("throttle\n"); break; case PERF_RECORD_UNTHROTTLE: g_print ("unthrottle\n"); break; case PERF_RECORD_FORK: process_fork (collector, &event->fork); break; case PERF_RECORD_READ: break; case PERF_RECORD_SAMPLE: process_sample (collector, &event->sample); break; default: g_warning ("unknown event: %d (%d)\n", event->header.type, event->header.size); break; } d_print ("\n"); } gboolean collector_start (Collector *collector, pid_t pid, GError **err) { int n_cpus = get_n_cpus (); int i; counter_t *output; if (!collector->tracker) collector->tracker = tracker_new (); output = NULL; for (i = 0; i < n_cpus; ++i) { counter_t *counter = counter_new (collector, pid, i, output, err); if (!counter) { GList *list; for (list = collector->counters; list != NULL; list = list->next) counter_free (list->data); collector->tracker = NULL; return FALSE; } collector->counters = g_list_append (collector->counters, counter); if (!output) output = counter; } enable_counters (collector); return TRUE; } void collector_stop (Collector *collector) { GList *list; if (!collector->counters) return; /* Read any remaining data */ for (list = collector->counters; list != NULL; list = list->next) { counter_t *counter = list->data; if (counter->data) on_read (counter); counter_free (counter); } g_list_free (collector->counters); collector->counters = NULL; } int collector_get_n_samples (Collector *collector) { return collector->n_samples; } Profile * collector_create_profile (Collector *collector) { /* The collector must be stopped when you create a profile */ g_assert (!collector->counters); return tracker_create_profile (collector->tracker); } GQuark collector_error_quark (void) { static GQuark q = 0; if (q == 0) q = g_quark_from_static_string ("collector-error-quark"); return q; } sysprof-1.2.0/treeviewutils.c0000644000175000017500000002363312021176713013226 00000000000000/* MemProf -- memory profiler and leak detector * Copyright 2002, Soeren Sandmann (sandmann@daimi.au.dk) * Copyright 2003, 2004, Red Hat, Inc. * * Sysprof -- Sampling, systemwide CPU profiler * Copyright 2004, 2005, 2006, 2007, 2008 Soeren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*====*/ #include "treeviewutils.h" static void on_column_clicked (GtkTreeViewColumn *column, gpointer data); typedef struct { int model_column; GtkSortType default_order; } SortInfo; static void set_sort_info (GtkTreeView *view, GtkTreeViewColumn *column, int model_column, GtkSortType default_order) { SortInfo *info; info = g_new0 (SortInfo, 1); info->model_column = model_column; info->default_order = default_order; gtk_tree_view_column_set_clickable (column, TRUE); g_object_set_data (G_OBJECT (column), "column_info", info); g_signal_connect (column, "clicked", G_CALLBACK (on_column_clicked), view); } static SortInfo * get_sort_info (GtkTreeViewColumn *column) { return g_object_get_data (G_OBJECT (column), "column_info"); } static GtkTreeViewColumn * find_column_by_model_column (GtkTreeView *view, int model_column) { GList *columns = gtk_tree_view_get_columns (view); GList *list; GtkTreeViewColumn *result = NULL; for (list = columns; list != NULL; list = list->next) { GtkTreeViewColumn *column = list->data; SortInfo *info = get_sort_info (column); if (info->model_column == model_column) result = column; } g_list_free (columns); return result; } void tree_view_set_sort_column (GtkTreeView *view, int model_column, int sort_type) { GList *columns, *list; GtkTreeSortable *sortable; GtkTreeViewColumn *column = find_column_by_model_column (view, model_column); SortInfo *info = get_sort_info (column); /* For each column in the view, unset the sort indicator */ columns = gtk_tree_view_get_columns (view); for (list = columns; list != NULL; list = list->next) { GtkTreeViewColumn *col = GTK_TREE_VIEW_COLUMN (list->data); gtk_tree_view_column_set_sort_indicator (col, FALSE); } /* Set the sort indicator for this column */ gtk_tree_view_column_set_sort_indicator (column, TRUE); gtk_tree_view_column_set_sort_order (column, sort_type); /* And sort the column */ sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (view)); gtk_tree_sortable_set_sort_column_id (sortable, info->model_column, sort_type); } static void on_column_clicked (GtkTreeViewColumn *column, gpointer data) { GtkTreeView *view = data; GtkSortType sort_type; SortInfo *info = get_sort_info (column); /* Find out what our current sort indicator is. If it is NONE, then * select the default for the column, otherwise, select the opposite */ if (!gtk_tree_view_column_get_sort_indicator (column)) { sort_type = info->default_order; } else { if (gtk_tree_view_column_get_sort_order (column) == GTK_SORT_ASCENDING) sort_type = GTK_SORT_DESCENDING; else sort_type = GTK_SORT_ASCENDING; } tree_view_set_sort_column (view, info->model_column, sort_type); } GtkTreeViewColumn * add_plain_text_column (GtkTreeView *view, const gchar *title, gint model_column) { GtkCellRenderer *renderer; GtkTreeViewColumn *column; renderer = gtk_cell_renderer_text_new (); g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); column = gtk_tree_view_column_new_with_attributes (title, renderer, "text", model_column, NULL); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_append_column (view, column); set_sort_info (view, column, model_column, GTK_SORT_ASCENDING); return column; } static void pointer_to_text (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) { gpointer p; gchar *text; int column = GPOINTER_TO_INT (data); gtk_tree_model_get (tree_model, iter, column, &p, -1); text = g_strdup_printf ("%p", p); g_object_set (cell, "text", text, NULL); g_free (text); } typedef struct { int column; char *format; } ColumnInfo; static void double_to_text (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) { gdouble d; gchar *text; ColumnInfo *info = data; gtk_tree_model_get (tree_model, iter, info->column, &d, -1); text = g_strdup_printf (info->format, d); g_object_set (cell, "markup", text, NULL); g_free (text); } static void free_column_info (void *data) { ColumnInfo *info = data; g_free (info->format); g_free (info); } GtkTreeViewColumn * add_double_format_column (GtkTreeView *view, const gchar *title, gint model_column, const char *format) { GtkCellRenderer *renderer; GtkTreeViewColumn *column; ColumnInfo *column_info = g_new (ColumnInfo, 1); renderer = gtk_cell_renderer_text_new (); g_object_set (renderer, "xalign", 1.0, NULL); column = gtk_tree_view_column_new (); gtk_tree_view_column_set_title (column, title); gtk_tree_view_column_pack_start (column, renderer, TRUE); gtk_tree_view_column_set_resizable (column, FALSE); column_info->column = model_column; column_info->format = g_strdup (format); gtk_tree_view_column_set_cell_data_func ( column, renderer, double_to_text, column_info, free_column_info); gtk_tree_view_append_column (view, column); set_sort_info (view, column, model_column, GTK_SORT_DESCENDING); return column; } GtkTreeViewColumn * add_pointer_column (GtkTreeView *view, const gchar *title, gint model_column) { GtkCellRenderer *renderer; GtkTreeViewColumn *column; renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new (); if (title) gtk_tree_view_column_set_title (column, title); gtk_tree_view_column_pack_start (column, renderer, TRUE); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_column_set_cell_data_func ( column, renderer, pointer_to_text, GINT_TO_POINTER (model_column), NULL); gtk_tree_view_append_column (view, column); return column; } void tree_view_set_model_with_default_sort (GtkTreeView *view, GtkTreeModel *model, int model_column, GtkSortType default_sort) { int column; GtkSortType type; GtkTreeSortable *old_model; GtkAdjustment *adjustment; old_model = GTK_TREE_SORTABLE (gtk_tree_view_get_model (view)); if (!(old_model && gtk_tree_sortable_get_sort_column_id ( GTK_TREE_SORTABLE (old_model), &column, &type))) { column = model_column; type = default_sort; } /* Setting the sort column here prevents the "rows_reordered" * signal from being emitted when the model is attached to * a treeview. This is desirable because at that point there * is a handler attached, which means the signal will actually * be emitted. */ gtk_tree_sortable_set_sort_column_id ( GTK_TREE_SORTABLE (model), column, type); gtk_tree_view_set_model (view, model); tree_view_set_sort_column (view, column, type); /* Workaround for GTK+ crack, see bug 405625 */ adjustment = gtk_tree_view_get_vadjustment (view); if (adjustment) gtk_adjustment_set_value (adjustment, 0); } static void process_iter (GtkTreeView *view, GtkTreeIter *iter, VisibleCallback callback, gpointer data) { GtkTreeModel *model = gtk_tree_view_get_model (view); GtkTreePath *path; GtkTreeIter child; path = gtk_tree_model_get_path (model, iter); callback (view, path, iter, data); if (gtk_tree_view_row_expanded (view, path)) { if (gtk_tree_model_iter_children (model, &child, iter)) { do { process_iter (view, &child, callback, data); } while (gtk_tree_model_iter_next (model, &child)); } } gtk_tree_path_free (path); } void tree_view_foreach_visible (GtkTreeView *view, VisibleCallback callback, gpointer data) { GtkTreeModel *model = gtk_tree_view_get_model (view); GtkTreeIter iter; if (model && gtk_tree_model_get_iter_first (model, &iter)) process_iter (view, &iter, callback, data); } /* Not really a *treeview* utility, but there isn't really a * better place to put it */ void set_error (GError **err, gint domain, gint code, const char *format, va_list args) { char *msg; if (!err) return; msg = g_strdup_vprintf (format, args); if (*err == NULL) { *err = g_error_new_literal (G_MARKUP_ERROR, code, msg); } else { /* Warning text from GLib */ g_warning ("GError set over the top of a previous GError or uninitialized memory.\n" "This indicates a bug in someone's code. You must ensure an error is NULL before it's set.\n" "The overwriting error message was: %s", msg); } g_free (msg); } sysprof-1.2.0/sysprof-icon-24.png0000644000175000017500000000267312021176713013534 00000000000000PNG  IHDRw=gAMAOX2tEXtSoftwareAdobe ImageReadyqe<MIDATxڔV{LSg-}W@XC&İ j-,s[Lƙ8X2ȜY&DM#Y2pjX(R@ XRjܲsQ {};bxx+!!!;999gff&zhi<>Nwycd` gv{۷OB!s*v׮];R$o;[D;NG~V . >-'A{WVsss?=F.EWE$2ֲHkhܢR6 p8|D& (za,<9"HouFa?!ٖ"v  H1Zvƍ{\'I4n;w>BvvmBa$ I&P$%g(tIm^bIVЭСC{q=|)c M!Wi-f tA  ۋ}}}^$SSSw\NᱣGiި:%]b^IM?iWW;,>YJJJ3L'?C^ӈ t_F WvWe[*i011QÝʶ?Z}*Fю(VkVp:R@ xU U܂blV˅JңY@QzzzrW-t!$•!+(: ذqTJ9W(kHb (qd"<53™3DZuzHc*j O LOOYaZh@ !Q5il 0֑d| RmTP*\bbLNNz  LYdCNhT\h~ʵ d"LGLYuFඛpt3 .#&槹H"d\zc0r2=V&2`cg kU,`}!0BU L;ԩgkQ2B0h701F{惐%V)ZG{7dqMzԇA=q8Ƿl6\{ `̇_ZguA cmh/tey9AxE4+6 C+gn,*˱urΏóD#_UPPp֪GFF F91g8݁ae0NE"HvKL@ 7 ;hoizhӲ $JGht>IYWR3RR}gwOw<:IsJc>_RLrGIENDB`sysprof-1.2.0/Makefile.am0000644000175000017500000000426412022706134012177 00000000000000ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} #SUBDIRS = $(MODULE_SUBDIR) #DIST_SUBDIRS = module bin_PROGRAMS = sysprof-cli if BUILD_GUI bin_PROGRAMS += sysprof endif SYSPROF_CORE = \ binfile.h \ binfile.c \ collector.c \ collector.h \ demangle.c \ elfparser.c \ elfparser.h \ profile.h \ profile.c \ sfile.h \ sfile.c \ sformat.h \ sformat.c \ stackstash.h \ stackstash.c \ tracker.h \ tracker.c \ unwind.h \ unwind.c \ watch.h \ watch.c \ \ util.h # module/sysprof-module.h # # GUI version # if BUILD_GUI sysprof_SOURCES = \ $(SYSPROF_CORE) \ footreestore.c \ footreestore.h \ footreedatalist.h \ footreedatalist.c \ treeviewutils.h \ treeviewutils.c \ sysprof.c sysprof_CPPFLAGS = \ $(GUI_DEP_CFLAGS) \ -DDATADIR=\"$(pkgdatadir)\" \ -DPIXMAPDIR=\"$(pixmapsdir)\" sysprof_LDADD = $(GUI_DEP_LIBS) endif udevdir = $(sysconfdir)/udev/rules.d dist_udev_DATA = 60-sysprof.rules pixmapsdir = $(datadir)/pixmaps dist_pkgdata_DATA = sysprof.glade dist_pixmaps_DATA = sysprof-icon-16.png sysprof-icon-24.png sysprof-icon-32.png sysprof-icon-48.png # # Command line version # sysprof_cli_SOURCES = \ $(SYSPROF_CORE) \ signal-handler.h \ signal-handler.c \ sysprof-cli.c sysprof_cli_CPPFLAGS = \ $(CORE_DEP_CFLAGS) sysprof_cli_LDADD = $(CORE_DEP_LIBS) # # Module stuff # #EXTRA_DIST = \ # module/sysprof-module.c \ # module/sysprof-module.h \ # module/Makefile #insert-module: # /sbin/modprobe -r sysprof-module # /sbin/modprobe sysprof-module # # Test programs # noinst_PROGRAMS = testelf testunwind testdemangle # testunwind testunwind_SOURCES = \ testunwind.c \ demangle.c \ elfparser.c \ elfparser.h \ unwind.c \ unwind.h testunwind_CPPFLAGS = $(CORE_DEP_CFLAGS) testunwind_LDADD = $(CORE_DEP_LIBS) # testelf testelf_SOURCES = \ testelf.c \ demangle.c \ elfparser.c \ elfparser.h testelf_CPPFLAGS = $(CORE_DEP_CFLAGS) testelf_LDADD = $(CORE_DEP_LIBS) # testdemangle testdemangle_SOURCES = \ testdemangle.c \ elfparser.c \ elfparser.h \ demangle.c testdemangle_CPPFLAGS = $(CORE_DEP_CFLAGS) testdemangle_LDADD = $(CORE_DEP_LIBS) sysprof-1.2.0/sysprof-cli.c0000644000175000017500000000747512021176713012573 00000000000000/* Sysprof -- Sampling, systemwide CPU profiler * Copyright 2005, Lorenzo Colitti * Copyright 2005, Soren Sandmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include "stackstash.h" #include "profile.h" #include "watch.h" #include "signal-handler.h" #include "collector.h" typedef struct Application Application; struct Application { Collector * collector; char * outfile; GMainLoop * main_loop; }; static void dump_data (Application *app) { GError *err = NULL; Profile *profile; printf ("Saving profile (%d samples) in %s ... ", collector_get_n_samples (app->collector), app->outfile); fflush (stdout); collector_stop (app->collector); profile = collector_create_profile (app->collector); profile_save (profile, app->outfile, &err); if (err) { printf ("failed\n"); fprintf (stderr, "Error saving %s: %s\n", app->outfile, err->message); exit (1); } else { printf ("done\n\n"); } } static void signal_handler (int signo, gpointer data) { Application *app = data; dump_data (app); while (g_main_context_iteration (NULL, FALSE)) ; g_main_loop_quit (app->main_loop); } static char * usage_msg (const char *name) { return g_strdup_printf ( "Usage: \n" " %s \n" "\n" "On SIGTERM or SIGINT (Ctrl-C) the profile will be written to ", name); } static gboolean file_exists_and_is_dir (const char *name) { return g_file_test (name, G_FILE_TEST_EXISTS) && g_file_test (name, G_FILE_TEST_IS_DIR); } static void die (const char *err_msg) { if (err_msg) fprintf (stderr, "\n%s\n\n", err_msg); exit (-1); } static int opt_pid = -1; static GOptionEntry entries[] = { { "pid", 'p', 0, G_OPTION_ARG_INT, &opt_pid, "Make sysprof specific to a task", NULL }, { NULL } }; int main (int argc, char *argv[]) { Application *app; GOptionContext *context; GError *err; err = NULL; context = g_option_context_new ("- Sysprof"); g_option_context_add_main_entries (context, entries, NULL); if (!g_option_context_parse (context, &argc, &argv, &err)) { g_print ("Failed to parse options: %s\n", err->message); return 1; } app = g_new0 (Application, 1); app->collector = collector_new (FALSE, NULL, NULL); app->outfile = g_strdup (argv[1]); app->main_loop = g_main_loop_new (NULL, 0); if (!collector_start (app->collector, (pid_t) opt_pid, &err)) die (err->message); if (argc < 2) die (usage_msg (argv[0])); if (!signal_set_handler (SIGTERM, signal_handler, app, &err)) die (err->message); if (!signal_set_handler (SIGINT, signal_handler, app, &err)) die (err->message); if (file_exists_and_is_dir (app->outfile)) { char *msg = g_strdup_printf ("Can't write to %s: is a directory\n", app->outfile); die (msg); } g_main_loop_run (app->main_loop); signal_unset_handler (SIGTERM); signal_unset_handler (SIGINT); return 0; }