From: mar77i Date: Sun, 22 Mar 2026 10:03:05 +0000 (+0100) Subject: break up source files, fix get_field_labels X-Git-Url: https://git.mar77i.info/?a=commitdiff_plain;h=a759bea67fe5ff9a3a8007e15c465e6f069cd1a2;p=perftrace break up source files, fix get_field_labels --- diff --git a/Makefile b/Makefile index fb1598b..56ff05a 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ LDLIBS += all: perftrace work_some -perftrace: perftrace.o +perftrace: perftrace.o parse_args.o work_some: work_some.o include global.mk diff --git a/list.h b/list.h new file mode 100644 index 0000000..a924630 --- /dev/null +++ b/list.h @@ -0,0 +1,38 @@ + +// list.h + +#ifndef LIST_H +#define LIST_H + +#include +#include + +struct list { + size_t len, allo; + void *data; +}; + +#define LIST_EMPTY ((struct list){ 0, 0, NULL }) +#define LIST_ITEMS(l, t) ((t*)(l).data) +#define LIST_POS(p, l, t) (size_t)((p) - LIST_ITEMS((l), t)) +#define LIST_AT(l, i, t) (LIST_ITEMS((l), t) + i) + +static inline int list_maybe_grow( + struct list *l, size_t new_len, size_t item_size +) { + void *np; + if (new_len <= l->allo) + return 0; + do + l->allo = l->allo ? l->allo * 2 : 8; + while (new_len > l->allo); + np = realloc(l->data, l->allo * item_size); + if (np == NULL) { + perror("realloc"); + return -1; + } + l->data = np; + return 0; +} + +#endif // LIST_H diff --git a/parse_args.c b/parse_args.c new file mode 100644 index 0000000..25494b9 --- /dev/null +++ b/parse_args.c @@ -0,0 +1,116 @@ + +// parse_args.c + +#include +#include + +#include "parse_args.h" + +static inline int parse_pid(const char *ptr, struct arg_pid_item *new_item) { + unsigned long pid = 0; + do { + if (parse_unsigned_long(&pid, *ptr, NULL) < 0) + return -1; + ptr++; + } while (*ptr != '\0' && *ptr != '+' && *ptr != '*'); + *new_item = (struct arg_pid_item){ pid, *ptr }; + if (ptr[0] != '\0' && ptr[1] != '\0') + return -1; + return 0; +} + +static inline int parse_arg_pid(int argc, char ***argv, struct list *arg_pids) { + if ( + list_maybe_grow( + arg_pids, ++arg_pids->len, sizeof (struct arg_pid_item) + ) < 0 + ) + return -1; + if ((**argv)[5] == '=') { + if ( + parse_pid( + **argv + 6, + LIST_ITEMS(*arg_pids, struct arg_pid_item) + arg_pids->len - 1 + ) < 0 + ) + return -1; + } else if ((**argv)[5] == '\0') { + if ( + --argc == 0 + || parse_pid( + *++(*argv), + LIST_ITEMS(*arg_pids, struct arg_pid_item) + arg_pids->len - 1 + ) < 0 + ) + return -1; + } else + return -1; + return argc; +} + +static inline int parse_delay(const char *ptr, struct timeval *delay) { + register unsigned long fractions; + *delay = (struct timeval){ 0, 0 }; + for (; *ptr != '\0' && *ptr != '.'; ptr++) + if (parse_unsigned_long((unsigned long*)&delay->tv_sec, *ptr, NULL) < 0) + return -1; + ptr += *ptr != '\0'; + for ( + fractions = MICRO_IN_SEC / 10; + *ptr && fractions > 0; + ptr++, fractions /= 10 + ) + if (*ptr < '0' || *ptr > '9') + return -1; + else + delay->tv_usec += fractions * (*ptr - '0'); + return 0; +} + +static inline int parse_arg_delay( + int argc, char ***argv, struct timeval *delay +) { + long clock_ticks; + if ((**argv)[7] == '=') { + if (parse_delay(**argv + 8, delay) < 0) + return -1; + } else if ((**argv)[7] == '\0') { + if (--argc == 0 || parse_delay(*++(*argv), delay) < 0) + return -1; + } else + return -1; + clock_ticks = sysconf(_SC_CLK_TCK); + if ( + (clock_ticks <= 1 && delay->tv_sec < 1) || ( + delay->tv_sec < 1 && delay->tv_usec < MICRO_IN_SEC / clock_ticks + ) + ) { + fprintf(stderr, "Error: delay too small!\n"); + return -1; + } + return argc; +} + +int parse_args( + int argc, + char **argv, + struct list *pids, + struct timeval *delay, + int *humanize_mem +) { + for (argc--, argv++; argc > 0; argc--, argv++) { + if (strncmp(*argv, "--pid", 5) == 0) + argc = parse_arg_pid(argc, &argv, pids); + else if (strncmp(*argv, "--delay", 7) == 0) + argc = parse_arg_delay(argc, &argv, delay); + else if (strcmp(*argv, "--humanize") == 0) + *humanize_mem = 1; + else + argc = -1; + if (argc == -1) { + fprintf(stderr, "Error: Could not process argument: '%s'\n", *argv); + return -1; + } + } + return 0; +} diff --git a/parse_args.h b/parse_args.h new file mode 100644 index 0000000..ef42c17 --- /dev/null +++ b/parse_args.h @@ -0,0 +1,42 @@ + +// parse_args.h + +#ifndef PARSE_ARGS_H +#define PARSE_ARGS_H + +#include "list.h" + +#define MICRO_IN_SEC 1000000 + +struct arg_pid_item { + pid_t pid; + char mode; +}; + +int parse_args( + int argc, + char **argv, + struct list *pids, + struct timeval *delay, + int *humanize_mem +); + +static inline int parse_unsigned_long( + unsigned long *result, char c, char *label +) { + register unsigned long new_value = 10 * *result + c - '0'; + if (c >= '0' && new_value / 10 == *result) { + *result = new_value; + return 0; + } + if (label) + fprintf( + stderr, + "Error: %s: invalid character or overflow ('%c')\n", + label, + c + ); + return -1; +} + +#endif // PARSE_ARGS_H diff --git a/perftrace.c b/perftrace.c index 01502e5..1af5435 100644 --- a/perftrace.c +++ b/perftrace.c @@ -6,179 +6,21 @@ #include #include #include -#include -#include #include #include #include #include +#include "list.h" +#include "parse_args.h" + #define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) -#define MICRO_IN_SEC 1000000 #define NANO_IN_SEC 1000000000 #define TIMESPEC_TO_DOUBLE(t) \ ((double)(t).tv_sec + (double)(t).tv_nsec / NANO_IN_SEC) #define TIMESPEC_ISZERO(t) ((t).tv_sec == 0 && (t).tv_nsec == 0) -struct list { - size_t len, allo; - void *data; -}; -#define LIST_EMPTY ((struct list){ 0, 0, NULL }) -#define LIST_ITEMS(l, t) ((t*)(l).data) -#define LIST_POS(p, l, t) (size_t)((p) - LIST_ITEMS((l), t)) -#define LIST_AT(l, i, t) (LIST_ITEMS((l), t) + i) - -static inline int list_maybe_grow( - struct list *l, size_t new_len, size_t item_size -) { - void *np; - if (new_len <= l->allo) - return 0; - do - l->allo = l->allo ? l->allo * 2 : 8; - while (new_len > l->allo); - np = realloc(l->data, l->allo * item_size); - if (np == NULL) { - perror("realloc"); - return -1; - } - l->data = np; - return 0; -} - -struct arg_pid_item { - pid_t pid; - char mode; -}; - -static inline int parse_unsigned_long( - unsigned long *result, char c, char *label -) { - register unsigned long new_value = 10 * *result + c - '0'; - if (c >= '0' && new_value / 10 == *result) { - *result = new_value; - return 0; - } - if (label) - fprintf( - stderr, - "Error: %s: invalid character or overflow ('%c')\n", - label, - c - ); - return -1; -} - -static inline int parse_pid(const char *ptr, struct arg_pid_item *new_item) { - unsigned long pid = 0; - do { - if (parse_unsigned_long(&pid, *ptr, NULL) < 0) - return -1; - ptr++; - } while (*ptr != '\0' && *ptr != '+' && *ptr != '*'); - *new_item = (struct arg_pid_item){ pid, *ptr }; - if (ptr[0] != '\0' && ptr[1] != '\0') - return -1; - return 0; -} - -static inline int parse_arg_pid(int argc, char ***argv, struct list *arg_pids) { - if ( - list_maybe_grow( - arg_pids, ++arg_pids->len, sizeof (struct arg_pid_item) - ) < 0 - ) - return -1; - if ((**argv)[5] == '=') { - if ( - parse_pid( - **argv + 6, - LIST_ITEMS(*arg_pids, struct arg_pid_item) + arg_pids->len - 1 - ) < 0 - ) - return -1; - } else if ((**argv)[5] == '\0') { - if ( - --argc == 0 - || parse_pid( - *++(*argv), - LIST_ITEMS(*arg_pids, struct arg_pid_item) + arg_pids->len - 1 - ) < 0 - ) - return -1; - } else - return -1; - return argc; -} - -static inline int parse_delay(const char *ptr, struct timeval *delay) { - register unsigned long fractions; - *delay = (struct timeval){ 0, 0 }; - for (; *ptr != '\0' && *ptr != '.'; ptr++) - if (parse_unsigned_long((unsigned long*)&delay->tv_sec, *ptr, NULL) < 0) - return -1; - ptr += *ptr != '\0'; - for ( - fractions = MICRO_IN_SEC / 10; - *ptr && fractions > 0; - ptr++, fractions /= 10 - ) - if (*ptr < '0' || *ptr > '9') - return -1; - else - delay->tv_usec += fractions * (*ptr - '0'); - return 0; -} - -static inline int parse_arg_delay( - int argc, char ***argv, struct timeval *delay -) { - long clock_ticks; - if ((**argv)[7] == '=') { - if (parse_delay(**argv + 8, delay) < 0) - return -1; - } else if ((**argv)[7] == '\0') { - if (--argc == 0 || parse_delay(*++(*argv), delay) < 0) - return -1; - } else - return -1; - clock_ticks = sysconf(_SC_CLK_TCK); - if ( - (clock_ticks <= 1 && delay->tv_sec < 1) || ( - delay->tv_sec < 1 && delay->tv_usec < MICRO_IN_SEC / clock_ticks - ) - ) { - fprintf(stderr, "Error: delay too small!\n"); - return -1; - } - return argc; -} - -int parse_args( - int argc, - char **argv, - struct list *pids, - struct timeval *delay, - int *humanize_mem -) { - for (argc--, argv++; argc > 0; argc--, argv++) { - if (strncmp(*argv, "--pid", 5) == 0) - argc = parse_arg_pid(argc, &argv, pids); - else if (strncmp(*argv, "--delay", 7) == 0) - argc = parse_arg_delay(argc, &argv, delay); - else if (strcmp(*argv, "--humanize") == 0) - *humanize_mem = 1; - else - argc = -1; - if (argc == -1) { - fprintf(stderr, "Error: Could not process argument: '%s'\n", *argv); - return -1; - } - } - return 0; -} static int alarm_set, int_set, page_size; @@ -205,27 +47,21 @@ struct pid_item { }; static inline void get_field_labels(char digits, char *buffer) { - const char *s = "ppidvsizerss"; + const char *s = "ppid\0vsize\0rss"; char *ptr = buffer; for (digits &= 7; digits; digits >>= 1) { if (!(digits & 1)) { - s += 4; - if (*s != 'u') - s++; + s += 5 + (s[4] != '\0'); continue; } if (ptr > buffer) { *ptr++ = ','; *ptr++ = ' '; } - *ptr++ = *s++; - *ptr++ = *s++; - *ptr++ = *s++; - if (!*s) - break; - *ptr++ = *s++; - if (*s != 'u') + do *ptr++ = *s++; + while (*s); + s++; } *ptr = '\0'; }