#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
struct udev_device {
  int dummy;
};

/* Variables and functions */
int /*<<< orphan*/ print_all_attributes(struct udev_device *, char *);
int /*<<< orphan*/ printf(char *, ...);
char *udev_device_get_devpath(struct udev_device *);
char *udev_device_get_driver(struct udev_device *);
struct udev_device *udev_device_get_parent(struct udev_device *);
char *udev_device_get_subsystem(struct udev_device *);
char *udev_device_get_sysname(struct udev_device *);
int print_device_chain(struct udev_device *device) {
  struct udev_device *device_parent;
  const char *str;
  printf(
      "\n"
      "Udevadm info starts with the device specified by the devpath and then\n"
      "walks up the chain of parent devices. It prints for every device\n"
      "found, all possible attributes in the udev rules key format.\n"
      "A rule to match, can be composed by the attributes of the device\n"
      "and the attributes from one single parent device.\n"
      "\n");
  printf("  looking at device '%s':\n", udev_device_get_devpath(device));
  printf("    KERNEL==\"%s\"\n", udev_device_get_sysname(device));
  str = udev_device_get_subsystem(device);
  if (str == NULL)
    str = "";
  printf("    SUBSYSTEM==\"%s\"\n", str);
  str = udev_device_get_driver(device);
  if (str == NULL)
    str = "";
  printf("    DRIVER==\"%s\"\n", str);
  print_all_attributes(device, "ATTR");
  device_parent = device;
  do {
    device_parent = udev_device_get_parent(device_parent);
    if (device_parent == NULL)
      break;
    printf("  looking at parent device '%s':\n",
           udev_device_get_devpath(device_parent));
    printf("    KERNELS==\"%s\"\n", udev_device_get_sysname(device_parent));
    str = udev_device_get_subsystem(device_parent);
    if (str == NULL)
      str = "";
    printf("    SUBSYSTEMS==\"%s\"\n", str);
    str = udev_device_get_driver(device_parent);
    if (str == NULL)
      str = "";
    printf("    DRIVERS==\"%s\"\n", str);
    print_all_attributes(device_parent, "ATTRS");
  } while (device_parent != NULL);
  return 0;
}


x86 assembly (clang, -O0):
<print_device_chain>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %rdi,-0x8(%rbp)
lea    0xe7d(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
mov    -0x8(%rbp),%rdi
call   1090 <udev_device_get_devpath@plt>
mov    %rax,%rsi
lea    0xf9d(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
mov    -0x8(%rbp),%rdi
call   1070 <udev_device_get_sysname@plt>
mov    %rax,%rsi
lea    0xf9e(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
mov    -0x8(%rbp),%rdi
call   1040 <udev_device_get_subsystem@plt>
mov    %rax,-0x18(%rbp)
cmpq   $0x0,-0x18(%rbp)
jne    11e1 <print_device_chain+0x71>
lea    0xf5c(%rip),%rax
mov    %rax,-0x18(%rbp)
mov    -0x18(%rbp),%rsi
lea    0xf7b(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
mov    -0x8(%rbp),%rdi
call   1080 <udev_device_get_driver@plt>
mov    %rax,-0x18(%rbp)
cmpq   $0x0,-0x18(%rbp)
jne    1216 <print_device_chain+0xa6>
lea    0xf27(%rip),%rax
mov    %rax,-0x18(%rbp)
mov    -0x18(%rbp),%rsi
lea    0xf5b(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
mov    -0x8(%rbp),%rdi
lea    0xf5b(%rip),%rsi
call   1050 <print_all_attributes@plt>
mov    -0x8(%rbp),%rax
mov    %rax,-0x10(%rbp)
mov    -0x10(%rbp),%rdi
call   1060 <udev_device_get_parent@plt>
mov    %rax,-0x10(%rbp)
cmpq   $0x0,-0x10(%rbp)
jne    125d <print_device_chain+0xed>
jmp    1316 <print_device_chain+0x1a6>
mov    -0x10(%rbp),%rdi
call   1090 <udev_device_get_devpath@plt>
mov    %rax,%rsi
lea    0xf23(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
mov    -0x10(%rbp),%rdi
call   1070 <udev_device_get_sysname@plt>
mov    %rax,%rsi
lea    0xf2b(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
mov    -0x10(%rbp),%rdi
call   1040 <udev_device_get_subsystem@plt>
mov    %rax,-0x18(%rbp)
cmpq   $0x0,-0x18(%rbp)
jne    12b4 <print_device_chain+0x144>
lea    0xe89(%rip),%rax
mov    %rax,-0x18(%rbp)
mov    -0x18(%rbp),%rsi
lea    0xf09(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
mov    -0x10(%rbp),%rdi
call   1080 <udev_device_get_driver@plt>
mov    %rax,-0x18(%rbp)
cmpq   $0x0,-0x18(%rbp)
jne    12e9 <print_device_chain+0x179>
lea    0xe54(%rip),%rax
mov    %rax,-0x18(%rbp)
mov    -0x18(%rbp),%rsi
lea    0xeea(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
mov    -0x10(%rbp),%rdi
lea    0xeeb(%rip),%rsi
call   1050 <print_all_attributes@plt>
cmpq   $0x0,-0x10(%rbp)
jne    1240 <print_device_chain+0xd0>
xor    %eax,%eax
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<print_device_chain>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
push   %rax
mov    %rdi,%rbx
lea    0xf28(%rip),%rdi
call   1030 <puts@plt>
mov    %rbx,%rdi
call   10a0 <udev_device_get_devpath@plt>
lea    0xe57(%rip),%rdi
mov    %rax,%rsi
xor    %eax,%eax
call   1040 <printf@plt>
mov    %rbx,%rdi
call   1080 <udev_device_get_sysname@plt>
lea    0xe59(%rip),%rdi
mov    %rax,%rsi
xor    %eax,%eax
call   1040 <printf@plt>
mov    %rbx,%rdi
call   1050 <udev_device_get_subsystem@plt>
test   %rax,%rax
lea    0xe4e(%rip),%r14
cmove  %r14,%rax
lea    0xe44(%rip),%rdi
mov    %rax,%rsi
xor    %eax,%eax
call   1040 <printf@plt>
mov    %rbx,%rdi
call   1090 <udev_device_get_driver@plt>
test   %rax,%rax
cmove  %r14,%rax
lea    0xe39(%rip),%rdi
mov    %rax,%rsi
xor    %eax,%eax
call   1040 <printf@plt>
lea    0xe3a(%rip),%rsi
mov    %rbx,%rdi
call   1060 <print_all_attributes@plt>
mov    %rbx,%rdi
call   1070 <udev_device_get_parent@plt>
test   %rax,%rax
je     12e5 <print_device_chain+0x165>
mov    %rax,%rbx
lea    0xe3e(%rip),%r15
lea    0xe4a(%rip),%r12
lea    0xe59(%rip),%r13
lea    0xe65(%rip),%rbp
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
mov    %rbx,%rdi
call   10a0 <udev_device_get_devpath@plt>
lea    0xdea(%rip),%rdi
mov    %rax,%rsi
xor    %eax,%eax
call   1040 <printf@plt>
mov    %rbx,%rdi
call   1080 <udev_device_get_sysname@plt>
mov    %r15,%rdi
mov    %rax,%rsi
xor    %eax,%eax
call   1040 <printf@plt>
mov    %rbx,%rdi
call   1050 <udev_device_get_subsystem@plt>
test   %rax,%rax
cmove  %r14,%rax
mov    %r12,%rdi
mov    %rax,%rsi
xor    %eax,%eax
call   1040 <printf@plt>
mov    %rbx,%rdi
call   1090 <udev_device_get_driver@plt>
test   %rax,%rax
cmove  %r14,%rax
mov    %r13,%rdi
mov    %rax,%rsi
xor    %eax,%eax
call   1040 <printf@plt>
mov    %rbx,%rdi
mov    %rbp,%rsi
call   1060 <print_all_attributes@plt>
mov    %rbx,%rdi
call   1070 <udev_device_get_parent@plt>
mov    %rax,%rbx
test   %rax,%rax
jne    1260 <print_device_chain+0xe0>
xor    %eax,%eax
add    $0x8,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
%struct.udev_device = type { i32 }
@.str = [314 x i8] c"\0AUdevadm info starts with the device specified by the devpath and then\0Awalks up the chain of parent devices. It prints for every device\0Afound, all possible attributes in the udev rules key format.\0AA rule to match, can be composed by the attributes of the device\0Aand the attributes from one single parent device.\0A\0A\00"
@.str.1 = [27 x i8] c" looking at device '%s':\0A\00"
@.str.2 = [18 x i8] c" KERNEL==\22%s\22\0A\00"
@.str.3 = [1 x i8] zeroinitializer
@.str.4 = [21 x i8] c" SUBSYSTEM==\22%s\22\0A\00"
@.str.5 = [18 x i8] c" DRIVER==\22%s\22\0A\00"
@.str.6 = [5 x i8] c"ATTR\00"
@.str.7 = [34 x i8] c" looking at parent device '%s':\0A\00"
@.str.8 = [19 x i8] c" KERNELS==\22%s\22\0A\00"
@.str.9 = [22 x i8] c" SUBSYSTEMS==\22%s\22\0A\00"
@.str.10 = [19 x i8] c" DRIVERS==\22%s\22\0A\00"
@.str.11 = [6 x i8] c"ATTRS\00"
define i32 @print_device_chain(%struct.udev_device* %0) {
%2 = alloca %struct.udev_device*
%3 = alloca %struct.udev_device*
%4 = alloca i8*
store %struct.udev_device* %0, %struct.udev_device** %2
%5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([314 x i8], [314 x i8]* @.str, i64 0, i64 0))
%6 = load %struct.udev_device*, %struct.udev_device** %2
%7 = call i8* @udev_device_get_devpath(%struct.udev_device* %6)
%8 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.1, i64 0, i64 0), i8* %7)
%9 = load %struct.udev_device*, %struct.udev_device** %2
%10 = call i8* @udev_device_get_sysname(%struct.udev_device* %9)
%11 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.2, i64 0, i64 0), i8* %10)
%12 = load %struct.udev_device*, %struct.udev_device** %2
%13 = call i8* @udev_device_get_subsystem(%struct.udev_device* %12)
store i8* %13, i8** %4
%14 = load i8*, i8** %4
%15 = icmp eq i8* %14, null
br i1 %15, label %16, label %17
16: ; preds = %1
store i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.3, i64 0, i64 0), i8** %4
br label %17
17: ; preds = %16, %1
%18 = load i8*, i8** %4
%19 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.4, i64 0, i64 0), i8* %18)
%20 = load %struct.udev_device*, %struct.udev_device** %2
%21 = call i8* @udev_device_get_driver(%struct.udev_device* %20)
store i8* %21, i8** %4
%22 = load i8*, i8** %4
%23 = icmp eq i8* %22, null
br i1 %23, label %24, label %25
24: ; preds = %17
store i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.3, i64 0, i64 0), i8** %4
br label %25
25: ; preds = %24, %17
%26 = load i8*, i8** %4
%27 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.5, i64 0, i64 0), i8* %26)
%28 = load %struct.udev_device*, %struct.udev_device** %2
%29 = call i32 @print_all_attributes(%struct.udev_device* %28, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.6, i64 0, i64 0))
%30 = load %struct.udev_device*, %struct.udev_device** %2
store %struct.udev_device* %30, %struct.udev_device** %3
br label %31
31: ; preds = %62, %25
%32 = load %struct.udev_device*, %struct.udev_device** %3
%33 = call %struct.udev_device* @udev_device_get_parent(%struct.udev_device* %32)
store %struct.udev_device* %33, %struct.udev_device** %3
%34 = load %struct.udev_device*, %struct.udev_device** %3
%35 = icmp eq %struct.udev_device* %34, null
br i1 %35, label %36, label %37
36: ; preds = %31
br label %65
37: ; preds = %31
%38 = load %struct.udev_device*, %struct.udev_device** %3
%39 = call i8* @udev_device_get_devpath(%struct.udev_device* %38)
%40 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([34 x i8], [34 x i8]* @.str.7, i64 0, i64 0), i8* %39)
%41 = load %struct.udev_device*, %struct.udev_device** %3
%42 = call i8* @udev_device_get_sysname(%struct.udev_device* %41)
%43 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.8, i64 0, i64 0), i8* %42)
%44 = load %struct.udev_device*, %struct.udev_device** %3
%45 = call i8* @udev_device_get_subsystem(%struct.udev_device* %44)
store i8* %45, i8** %4
%46 = load i8*, i8** %4
%47 = icmp eq i8* %46, null
br i1 %47, label %48, label %49
48: ; preds = %37
store i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.3, i64 0, i64 0), i8** %4
br label %49
49: ; preds = %48, %37
%50 = load i8*, i8** %4
%51 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.9, i64 0, i64 0), i8* %50)
%52 = load %struct.udev_device*, %struct.udev_device** %3
%53 = call i8* @udev_device_get_driver(%struct.udev_device* %52)
store i8* %53, i8** %4
%54 = load i8*, i8** %4
%55 = icmp eq i8* %54, null
br i1 %55, label %56, label %57
56: ; preds = %49
store i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.3, i64 0, i64 0), i8** %4
br label %57
57: ; preds = %56, %49
%58 = load i8*, i8** %4
%59 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.10, i64 0, i64 0), i8* %58)
%60 = load %struct.udev_device*, %struct.udev_device** %3
%61 = call i32 @print_all_attributes(%struct.udev_device* %60, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.11, i64 0, i64 0))
br label %62
62: ; preds = %57
%63 = load %struct.udev_device*, %struct.udev_device** %3
%64 = icmp ne %struct.udev_device* %63, null
br i1 %64, label %31, label %65
65: ; preds = %62, %36
ret i32 0
}

LLVM IR (-O2):
%struct.udev_device = type { i32 }
@.str.1 = [27 x i8] c" looking at device '%s':\0A\00"
@.str.2 = [18 x i8] c" KERNEL==\22%s\22\0A\00"
@.str.3 = [1 x i8] zeroinitializer
@.str.4 = [21 x i8] c" SUBSYSTEM==\22%s\22\0A\00"
@.str.5 = [18 x i8] c" DRIVER==\22%s\22\0A\00"
@.str.6 = [5 x i8] c"ATTR\00"
@.str.7 = [34 x i8] c" looking at parent device '%s':\0A\00"
@.str.8 = [19 x i8] c" KERNELS==\22%s\22\0A\00"
@.str.9 = [22 x i8] c" SUBSYSTEMS==\22%s\22\0A\00"
@.str.10 = [19 x i8] c" DRIVERS==\22%s\22\0A\00"
@.str.11 = [6 x i8] c"ATTRS\00"
@str = [313 x i8] c"\0AUdevadm info starts with the device specified by the devpath and then\0Awalks up the chain of parent devices. It prints for every device\0Afound, all possible attributes in the udev rules key format.\0AA rule to match, can be composed by the attributes of the device\0Aand the attributes from one single parent device.\0A\00"
define i32 @print_device_chain(%struct.udev_device* %0) {
%2 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([313 x i8], [313 x i8]* @str, i64 0, i64 0))
%3 = tail call i8* @udev_device_get_devpath(%struct.udev_device* %0)
%4 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([27 x i8], [27 x i8]* @.str.1, i64 0, i64 0), i8* %3)
%5 = tail call i8* @udev_device_get_sysname(%struct.udev_device* %0)
%6 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([18 x i8], [18 x i8]* @.str.2, i64 0, i64 0), i8* %5)
%7 = tail call i8* @udev_device_get_subsystem(%struct.udev_device* %0)
%8 = icmp eq i8* %7, null
%9 = select i1 %8, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.3, i64 0, i64 0), i8* %7
%10 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([21 x i8], [21 x i8]* @.str.4, i64 0, i64 0), i8* %9)
%11 = tail call i8* @udev_device_get_driver(%struct.udev_device* %0)
%12 = icmp eq i8* %11, null
%13 = select i1 %12, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.3, i64 0, i64 0), i8* %11
%14 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([18 x i8], [18 x i8]* @.str.5, i64 0, i64 0), i8* %13)
%15 = tail call i32 @print_all_attributes(%struct.udev_device* %0, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.6, i64 0, i64 0))
%16 = tail call %struct.udev_device* @udev_device_get_parent(%struct.udev_device* %0)
%17 = icmp eq %struct.udev_device* %16, null
br i1 %17, label %35, label %18
18: ; preds = %1, %18
%19 = phi %struct.udev_device* [ %33, %18 ], [ %16, %1 ]
%20 = tail call i8* @udev_device_get_devpath(%struct.udev_device* %19)
%21 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([34 x i8], [34 x i8]* @.str.7, i64 0, i64 0), i8* %20)
%22 = tail call i8* @udev_device_get_sysname(%struct.udev_device* %19)
%23 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([19 x i8], [19 x i8]* @.str.8, i64 0, i64 0), i8* %22)
%24 = tail call i8* @udev_device_get_subsystem(%struct.udev_device* %19)
%25 = icmp eq i8* %24, null
%26 = select i1 %25, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.3, i64 0, i64 0), i8* %24
%27 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([22 x i8], [22 x i8]* @.str.9, i64 0, i64 0), i8* %26)
%28 = tail call i8* @udev_device_get_driver(%struct.udev_device* %19)
%29 = icmp eq i8* %28, null
%30 = select i1 %29, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.3, i64 0, i64 0), i8* %28
%31 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([19 x i8], [19 x i8]* @.str.10, i64 0, i64 0), i8* %30)
%32 = tail call i32 @print_all_attributes(%struct.udev_device* %19, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.11, i64 0, i64 0))
%33 = tail call %struct.udev_device* @udev_device_get_parent(%struct.udev_device* %19)
%34 = icmp eq %struct.udev_device* %33, null
br i1 %34, label %35, label %18
35: ; preds = %18, %1
ret i32 0
}