summaryrefslogtreecommitdiffstats
path: root/src/client.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/client.S')
-rw-r--r--src/client.S879
1 files changed, 879 insertions, 0 deletions
diff --git a/src/client.S b/src/client.S
new file mode 100644
index 0000000..469f0f2
--- /dev/null
+++ b/src/client.S
@@ -0,0 +1,879 @@
+#include "abi.inc"
+#include "defs.inc"
+
+#define LK_URL -72
+#define LK_BODY -96
+#define LK_TMP -112
+#define LK_STATUS -120
+#define LK_MSG -128
+
+#define HL_URL -72
+#define HL_BODY -96
+#define HL_STATUS -104
+
+#define LM_IDX -48
+#define LM_CHUNK -56
+#define LM_SENT -64
+#define LM_MAP -72
+#define LM_ROWS -80
+#define LM_NROWS -88
+#define LM_STATUS -96
+#define LM_TMP -112
+#define LM_URL -136
+#define LM_BODY -160
+#define LM_J -168
+#define LM_K -176
+
+#define JF_KEY -48
+#define JF_VAL -56
+#define JF_OUT -64
+
+ .text
+
+PUBFUNC cepis_version
+ lea .Ls_version(%rip), %rax
+ ret
+ENDFUNC cepis_version
+
+PUBFUNC cepis_strerror
+ lea cepis__errnames(%rip), %rax
+ cmp $0, %edi
+ jl .Lse_unknown
+ cmp $8, %edi
+ jg .Lse_unknown
+ movslq %edi, %rdi
+ mov (%rax, %rdi, 8), %rax
+ ret
+.Lse_unknown:
+ lea .Ls_unknown(%rip), %rax
+ ret
+ENDFUNC cepis_strerror
+
+FUNC cepis__err_reset
+ test %rdi, %rdi
+ jz .Ler_out
+ movl $0, E_STATUS(%rdi)
+ movl $0, E_HTTP_STATUS(%rdi)
+ movq $0, E_RETRY_AFTER(%rdi)
+ movb $0, E_MESSAGE(%rdi)
+.Ler_out:
+ ret
+ENDFUNC cepis__err_reset
+
+FUNC cepis__err_set
+ PROLOGUE 8
+ test %rdi, %rdi
+ jz .Les_out
+ mov %esi, E_STATUS(%rdi)
+ mov %rdx, %r10
+ lea E_MESSAGE(%rdi), %rdi
+ mov $E_MSGLEN, %esi
+ mov %r10, %rdx
+ xor %eax, %eax
+ call snprintf@PLT
+.Les_out:
+ EPILOGUE
+ ret
+ENDFUNC cepis__err_set
+
+FUNC cepis__json_field
+ PROLOGUE 40
+ mov %rsi, %r15
+ movq $0, JF_KEY(%rbp)
+ movq $0, JF_VAL(%rbp)
+ movq $0, JF_OUT(%rbp)
+ call cepis__js_ws
+ mov %rax, %r12
+ cmpb $'{', (%r12)
+ jne .Ljf_out
+ lea 1(%r12), %rdi
+ call cepis__js_ws
+ mov %rax, %r12
+ cmpb $'}', (%r12)
+ je .Ljf_out
+.Ljf_pair:
+ cmpb $'"', (%r12)
+ jne .Ljf_out
+ mov %r12, %rdi
+ lea JF_KEY(%rbp), %rsi
+ call cepis__js_string
+ test %rax, %rax
+ jz .Ljf_out
+ mov %rax, %rdi
+ call cepis__js_ws
+ mov %rax, %r12
+ cmpb $':', (%r12)
+ jne .Ljf_out
+ lea 1(%r12), %rdi
+ call cepis__js_ws
+ mov %rax, %r12
+ cmpq $0, JF_OUT(%rbp)
+ jne .Ljf_skip
+ mov JF_KEY(%rbp), %rdi
+ mov %r15, %rsi
+ call strcmp@PLT
+ test %eax, %eax
+ jnz .Ljf_skip
+ movzbl (%r12), %eax
+ cmp $'{', %al
+ je .Ljf_skip
+ cmp $'[', %al
+ je .Ljf_skip
+ mov %r12, %rdi
+ lea JF_VAL(%rbp), %rsi
+ call cepis__js_scalar_text
+ test %rax, %rax
+ jz .Ljf_out
+ mov %rax, %r12
+ mov JF_VAL(%rbp), %rax
+ mov %rax, JF_OUT(%rbp)
+ jmp .Ljf_next
+.Ljf_skip:
+ mov %r12, %rdi
+ call cepis__js_skip
+ test %rax, %rax
+ jz .Ljf_out
+ mov %rax, %r12
+.Ljf_next:
+ mov JF_KEY(%rbp), %rdi
+ call free@PLT
+ movq $0, JF_KEY(%rbp)
+ mov %r12, %rdi
+ call cepis__js_ws
+ mov %rax, %r12
+ cmpb $',', (%r12)
+ jne .Ljf_out
+ lea 1(%r12), %rdi
+ call cepis__js_ws
+ mov %rax, %r12
+ jmp .Ljf_pair
+.Ljf_out:
+ mov JF_KEY(%rbp), %rdi
+ test %rdi, %rdi
+ jz .Ljf_ret
+ call free@PLT
+.Ljf_ret:
+ mov JF_OUT(%rbp), %rax
+ EPILOGUE
+ ret
+ENDFUNC cepis__json_field
+
+PUBFUNC cepis_client_new
+ PROLOGUE 40
+ mov %rsi, %r14
+ test %r14, %r14
+ jz .Lcn_usage
+ movq $0, (%r14)
+ mov %rdi, %r15
+ test %r15, %r15
+ jz .Lcn_alloc
+ mov C_MAX_ATTEMPTS(%r15), %eax
+ cmp $0, %eax
+ jl .Lcn_usage
+.Lcn_alloc:
+ mov $1, %rdi
+ mov $CL_SIZE, %rsi
+ call calloc@PLT
+ test %rax, %rax
+ jz .Lcn_nomem
+ mov %rax, %rbx
+ lea .Ls_default_url(%rip), %r12
+ test %r15, %r15
+ jz .Lcn_url
+ mov C_BASE_URL(%r15), %rax
+ test %rax, %rax
+ jz .Lcn_url
+ mov %rax, %r12
+.Lcn_url:
+ mov %r12, %rdi
+ call cepis__strdup
+ test %rax, %rax
+ jz .Lcn_nomem_free
+ mov %rax, CL_BASE_URL(%rbx)
+ mov %rax, %rdi
+ call strlen@PLT
+ mov CL_BASE_URL(%rbx), %rdx
+.Lcn_strip:
+ test %rax, %rax
+ jz .Lcn_ua
+ cmpb $'/', -1(%rdx, %rax, 1)
+ jne .Lcn_ua
+ dec %rax
+ movb $0, (%rdx, %rax, 1)
+ jmp .Lcn_strip
+.Lcn_ua:
+ lea .Ls_default_ua(%rip), %r12
+ test %r15, %r15
+ jz .Lcn_ua_dup
+ mov C_USER_AGENT(%r15), %rax
+ test %rax, %rax
+ jz .Lcn_ua_dup
+ mov %rax, %r12
+.Lcn_ua_dup:
+ mov %r12, %rdi
+ call cepis__strdup
+ test %rax, %rax
+ jz .Lcn_nomem_free
+ mov %rax, CL_USER_AGENT(%rbx)
+ movsd .Ld_timeout(%rip), %xmm0
+ movl $3, %eax
+ mov %eax, CL_MAX_ATTEMPTS(%rbx)
+ movsd %xmm0, CL_TIMEOUT(%rbx)
+ movsd .Ld_backoff_base(%rip), %xmm0
+ movsd %xmm0, CL_BACKOFF_BASE(%rbx)
+ movsd .Ld_backoff_max(%rip), %xmm0
+ movsd %xmm0, CL_BACKOFF_MAX(%rbx)
+ xorpd %xmm0, %xmm0
+ movsd %xmm0, CL_TOTAL_TIMEOUT(%rbx)
+ test %r15, %r15
+ jz .Lcn_seed
+ movsd C_TIMEOUT(%r15), %xmm0
+ xorpd %xmm1, %xmm1
+ comisd %xmm1, %xmm0
+ jbe .Lcn_attempts
+ movsd %xmm0, CL_TIMEOUT(%rbx)
+.Lcn_attempts:
+ mov C_MAX_ATTEMPTS(%r15), %eax
+ test %eax, %eax
+ jz .Lcn_bbase
+ mov %eax, CL_MAX_ATTEMPTS(%rbx)
+.Lcn_bbase:
+ movsd C_BACKOFF_BASE(%r15), %xmm0
+ xorpd %xmm1, %xmm1
+ comisd %xmm1, %xmm0
+ jbe .Lcn_bmax
+ movsd %xmm0, CL_BACKOFF_BASE(%rbx)
+.Lcn_bmax:
+ movsd C_BACKOFF_MAX(%r15), %xmm0
+ xorpd %xmm1, %xmm1
+ comisd %xmm1, %xmm0
+ jbe .Lcn_total
+ movsd %xmm0, CL_BACKOFF_MAX(%rbx)
+.Lcn_total:
+ movsd C_TOTAL_TIMEOUT(%r15), %xmm0
+ xorpd %xmm1, %xmm1
+ comisd %xmm1, %xmm0
+ jbe .Lcn_seed
+ movsd %xmm0, CL_TOTAL_TIMEOUT(%rbx)
+.Lcn_seed:
+ xor %edi, %edi
+ lea LOCAL1(%rbp), %rsi
+ call clock_gettime@PLT
+ mov LOCAL1(%rbp), %rax
+ mov LOCAL0(%rbp), %rdx
+ imul $1000000007, %rax, %rax
+ xor %rdx, %rax
+ xor %rbx, %rax
+ mov $1, %rdx
+ lock xadd %rdx, cepis__seed_counter(%rip)
+ imul $1103515245, %rdx, %rdx
+ xor %rdx, %rax
+ test %rax, %rax
+ jnz .Lcn_store_seed
+ movabs $0x9E3779B97F4A7C15, %rax
+.Lcn_store_seed:
+ mov %rax, CL_RNG(%rbx)
+ mov %rbx, (%r14)
+ xor %eax, %eax
+ EPILOGUE
+ ret
+.Lcn_nomem_free:
+ mov %rbx, %rdi
+ call cepis_client_free
+.Lcn_nomem:
+ mov $CEPIS_ERR_NOMEM, %eax
+ EPILOGUE
+ ret
+.Lcn_usage:
+ mov $CEPIS_ERR_USAGE, %eax
+ EPILOGUE
+ ret
+ENDFUNC cepis_client_new
+
+PUBFUNC cepis_client_free
+ PROLOGUE 8
+ test %rdi, %rdi
+ jz .Lcf_out
+ mov %rdi, %rbx
+ mov CL_BASE_URL(%rbx), %rdi
+ test %rdi, %rdi
+ jz .Lcf_ua
+ call free@PLT
+.Lcf_ua:
+ mov CL_USER_AGENT(%rbx), %rdi
+ test %rdi, %rdi
+ jz .Lcf_self
+ call free@PLT
+.Lcf_self:
+ mov %rbx, %rdi
+ call free@PLT
+.Lcf_out:
+ EPILOGUE
+ ret
+ENDFUNC cepis_client_free
+
+PUBFUNC cepis_default_client
+ PROLOGUE 24
+ mov cepis__default_client(%rip), %rax
+ test %rax, %rax
+ jnz .Ldc_out
+ xor %edi, %edi
+ lea LOCAL0(%rbp), %rsi
+ call cepis_client_new
+ test %eax, %eax
+ jnz .Ldc_fail
+ mov LOCAL0(%rbp), %rbx
+ xor %eax, %eax
+ lock cmpxchgq %rbx, cepis__default_client(%rip)
+ jz .Ldc_won
+ mov %rax, %r12
+ mov %rbx, %rdi
+ call cepis_client_free
+ mov %r12, %rax
+ EPILOGUE
+ ret
+.Ldc_won:
+ mov %rbx, %rax
+.Ldc_out:
+ EPILOGUE
+ ret
+.Ldc_fail:
+ xor %eax, %eax
+ EPILOGUE
+ ret
+ENDFUNC cepis_default_client
+
+FUNC cepis__default_client_destroy
+ PROLOGUE 8
+ xor %eax, %eax
+ xchg %rax, cepis__default_client(%rip)
+ test %rax, %rax
+ jz .Ldd_out
+ mov %rax, %rdi
+ call cepis_client_free
+.Ldd_out:
+ EPILOGUE
+ ret
+ENDFUNC cepis__default_client_destroy
+
+FUNC cepis__resolve
+ test %rdi, %rdi
+ jz .Lrc_default
+ mov %rdi, %rax
+ ret
+.Lrc_default:
+ jmp cepis_default_client
+ENDFUNC cepis__resolve
+
+PUBFUNC cepis_lookup
+ PROLOGUE 88
+ mov %rdi, %rbx
+ mov %rsi, %r13
+ mov %rdx, %r14
+ mov %rcx, %r15
+ test %r14, %r14
+ jz .Llk_usage
+ movq $0, (%r14)
+ mov %r15, %rdi
+ call cepis__err_reset
+ mov %rbx, %rdi
+ call cepis__resolve
+ test %rax, %rax
+ jz .Llk_nomem_bare
+ mov %rax, %rbx
+ movq $0, LK_URL(%rbp)
+ movq $0, LK_URL+8(%rbp)
+ movq $0, LK_URL+16(%rbp)
+ movq $0, LK_BODY(%rbp)
+ movq $0, LK_BODY+8(%rbp)
+ movq $0, LK_BODY+16(%rbp)
+ mov %r13, %rdi
+ lea LK_TMP(%rbp), %rsi
+ call cepis_normalize_cep
+ test %eax, %eax
+ jnz .Llk_invalid_input
+ lea LK_URL(%rbp), %rdi
+ mov CL_BASE_URL(%rbx), %rsi
+ call cepis__buf_appendz
+ test %eax, %eax
+ jnz .Llk_nomem
+ lea LK_URL(%rbp), %rdi
+ mov $'/', %esi
+ call cepis__buf_appendc
+ test %eax, %eax
+ jnz .Llk_nomem
+ lea LK_URL(%rbp), %rdi
+ lea LK_TMP(%rbp), %rsi
+ call cepis__buf_appendz
+ test %eax, %eax
+ jnz .Llk_nomem
+ mov %rbx, %rdi
+ mov LK_URL(%rbp), %rsi
+ xor %edx, %edx
+ lea LK_STATUS(%rbp), %rcx
+ lea LK_BODY(%rbp), %r8
+ mov %r15, %r9
+ call cepis__http_get
+ test %eax, %eax
+ jnz .Llk_httperr
+ mov LK_STATUS(%rbp), %eax
+ cmp $404, %eax
+ je .Llk_notfound
+ cmp $400, %eax
+ je .Llk_badcep
+ cmp $200, %eax
+ jne .Llk_badresp
+ mov LK_BODY(%rbp), %rdi
+ test %rdi, %rdi
+ jz .Llk_badresp
+ mov %r14, %rsi
+ call cepis__address_from_json
+ mov %eax, %r12d
+ test %eax, %eax
+ jz .Llk_done
+ cmp $CEPIS_ERR_NOMEM, %eax
+ je .Llk_nomem
+ mov %r15, %rdi
+ mov $CEPIS_ERR_INVALID_RESPONSE, %esi
+ lea .Lfmt_badjson(%rip), %rdx
+ mov LK_URL(%rbp), %rcx
+ xor %r8d, %r8d
+ call cepis__err_set
+ mov $CEPIS_ERR_INVALID_RESPONSE, %r12d
+ jmp .Llk_ret
+.Llk_done:
+ xor %r12d, %r12d
+.Llk_ret:
+ lea LK_URL(%rbp), %rdi
+ call cepis__buf_free
+ lea LK_BODY(%rbp), %rdi
+ call cepis__buf_free
+ mov %r12d, %eax
+ EPILOGUE
+ ret
+.Llk_httperr:
+ mov %eax, %r12d
+ jmp .Llk_ret
+.Llk_notfound:
+ mov %r15, %rdi
+ mov $CEPIS_ERR_NOT_FOUND, %esi
+ lea .Lfmt_notfound(%rip), %rdx
+ lea LK_TMP(%rbp), %rcx
+ xor %r8d, %r8d
+ call cepis__err_set
+ mov $CEPIS_ERR_NOT_FOUND, %r12d
+ jmp .Llk_ret
+.Llk_badcep:
+ movq $0, LK_MSG(%rbp)
+ mov LK_BODY(%rbp), %rdi
+ test %rdi, %rdi
+ jz .Llk_badcep_msg
+ lea .Ls_mensagem(%rip), %rsi
+ call cepis__json_field
+ mov %rax, LK_MSG(%rbp)
+.Llk_badcep_msg:
+ mov LK_MSG(%rbp), %r8
+ test %r8, %r8
+ jnz .Llk_badcep_emit
+ lea .Ls_rejected(%rip), %r8
+.Llk_badcep_emit:
+ mov %r15, %rdi
+ mov $CEPIS_ERR_INVALID_CEP, %esi
+ lea .Lfmt_badcep(%rip), %rdx
+ lea LK_TMP(%rbp), %rcx
+ call cepis__err_set
+ mov LK_MSG(%rbp), %rdi
+ test %rdi, %rdi
+ jz .Llk_badcep_done
+ call free@PLT
+.Llk_badcep_done:
+ mov $CEPIS_ERR_INVALID_CEP, %r12d
+ jmp .Llk_ret
+.Llk_badresp:
+ mov %r15, %rdi
+ mov $CEPIS_ERR_INVALID_RESPONSE, %esi
+ lea .Lfmt_status(%rip), %rdx
+ mov LK_STATUS(%rbp), %ecx
+ mov LK_URL(%rbp), %r8
+ call cepis__err_set
+ mov $CEPIS_ERR_INVALID_RESPONSE, %r12d
+ jmp .Llk_ret
+.Llk_invalid_input:
+ mov %r15, %rdi
+ mov $CEPIS_ERR_INVALID_CEP, %esi
+ lea .Lfmt_notdigits(%rip), %rdx
+ mov %r13, %rcx
+ test %rcx, %rcx
+ jnz .Llk_invalid_emit
+ lea .Ls_nullstr(%rip), %rcx
+.Llk_invalid_emit:
+ xor %r8d, %r8d
+ call cepis__err_set
+ mov $CEPIS_ERR_INVALID_CEP, %r12d
+ jmp .Llk_ret
+.Llk_nomem:
+ mov $CEPIS_ERR_NOMEM, %r12d
+ jmp .Llk_ret
+.Llk_nomem_bare:
+ mov $CEPIS_ERR_NOMEM, %eax
+ EPILOGUE
+ ret
+.Llk_usage:
+ mov $CEPIS_ERR_USAGE, %eax
+ EPILOGUE
+ ret
+ENDFUNC cepis_lookup
+
+PUBFUNC cepis_health
+ PROLOGUE 72
+ mov %rdi, %rbx
+ mov %rsi, %r14
+ mov %rdx, %r15
+ test %r14, %r14
+ jz .Lhl_usage
+ movq $0, (%r14)
+ mov %r15, %rdi
+ call cepis__err_reset
+ mov %rbx, %rdi
+ call cepis__resolve
+ test %rax, %rax
+ jz .Lhl_nomem_bare
+ mov %rax, %rbx
+ movq $0, HL_URL(%rbp)
+ movq $0, HL_URL+8(%rbp)
+ movq $0, HL_URL+16(%rbp)
+ movq $0, HL_BODY(%rbp)
+ movq $0, HL_BODY+8(%rbp)
+ movq $0, HL_BODY+16(%rbp)
+ lea HL_URL(%rbp), %rdi
+ mov CL_BASE_URL(%rbx), %rsi
+ call cepis__buf_appendz
+ test %eax, %eax
+ jnz .Lhl_nomem
+ lea HL_URL(%rbp), %rdi
+ lea .Ls_health_path(%rip), %rsi
+ call cepis__buf_appendz
+ test %eax, %eax
+ jnz .Lhl_nomem
+ mov %rbx, %rdi
+ mov HL_URL(%rbp), %rsi
+ mov $1, %edx
+ lea HL_STATUS(%rbp), %rcx
+ lea HL_BODY(%rbp), %r8
+ mov %r15, %r9
+ call cepis__http_get
+ test %eax, %eax
+ jnz .Lhl_httperr
+ mov HL_BODY(%rbp), %rdi
+ test %rdi, %rdi
+ jz .Lhl_badresp
+ mov %r14, %rsi
+ call cepis__health_from_json
+ mov %eax, %r12d
+ test %eax, %eax
+ jz .Lhl_ret
+ cmp $CEPIS_ERR_NOMEM, %eax
+ je .Lhl_nomem
+ jmp .Lhl_badresp
+.Lhl_ret:
+ lea HL_URL(%rbp), %rdi
+ call cepis__buf_free
+ lea HL_BODY(%rbp), %rdi
+ call cepis__buf_free
+ mov %r12d, %eax
+ EPILOGUE
+ ret
+.Lhl_httperr:
+ mov %eax, %r12d
+ jmp .Lhl_ret
+.Lhl_badresp:
+ mov %r15, %rdi
+ mov $CEPIS_ERR_INVALID_RESPONSE, %esi
+ lea .Lfmt_badjson(%rip), %rdx
+ mov HL_URL(%rbp), %rcx
+ xor %r8d, %r8d
+ call cepis__err_set
+ mov $CEPIS_ERR_INVALID_RESPONSE, %r12d
+ jmp .Lhl_ret
+.Lhl_nomem:
+ mov $CEPIS_ERR_NOMEM, %r12d
+ jmp .Lhl_ret
+.Lhl_nomem_bare:
+ mov $CEPIS_ERR_NOMEM, %eax
+ EPILOGUE
+ ret
+.Lhl_usage:
+ mov $CEPIS_ERR_USAGE, %eax
+ EPILOGUE
+ ret
+ENDFUNC cepis_health
+
+PUBFUNC cepis_lookup_many
+ PROLOGUE 136
+ mov %rdi, %rbx
+ mov %rsi, %r12
+ mov %rdx, %r13
+ mov %rcx, %r14
+ mov %r8, %r15
+ test %r14, %r14
+ jz .Llm_usage
+ movq $0, (%r14)
+ mov %r15, %rdi
+ call cepis__err_reset
+ test %r13, %r13
+ jz .Llm_check_ptr
+ test %r12, %r12
+ jz .Llm_usage
+.Llm_check_ptr:
+ mov %rbx, %rdi
+ call cepis__resolve
+ test %rax, %rax
+ jz .Llm_nomem_bare
+ mov %rax, %rbx
+ mov %r13, %rdi
+ test %rdi, %rdi
+ jnz .Llm_alloc
+ mov $1, %rdi
+.Llm_alloc:
+ mov $8, %rsi
+ call calloc@PLT
+ test %rax, %rax
+ jz .Llm_nomem_bare
+ mov %rax, (%r14)
+ movq $0, LM_MAP(%rbp)
+ movq $0, LM_ROWS(%rbp)
+ movq $0, LM_URL(%rbp)
+ movq $0, LM_URL+8(%rbp)
+ movq $0, LM_URL+16(%rbp)
+ movq $0, LM_BODY(%rbp)
+ movq $0, LM_BODY+8(%rbp)
+ movq $0, LM_BODY+16(%rbp)
+ movq $0, LM_IDX(%rbp)
+.Llm_chunk:
+ mov LM_IDX(%rbp), %rax
+ cmp %r13, %rax
+ jae .Llm_done
+ mov %r13, %rcx
+ sub %rax, %rcx
+ cmp $CEPIS_MAX_BATCH, %rcx
+ jbe .Llm_chunk_set
+ mov $CEPIS_MAX_BATCH, %rcx
+.Llm_chunk_set:
+ mov %rcx, LM_CHUNK(%rbp)
+ mov %rcx, %rdi
+ mov $8, %rsi
+ call calloc@PLT
+ test %rax, %rax
+ jz .Llm_nomem
+ mov %rax, LM_MAP(%rbp)
+ lea LM_URL(%rbp), %rdi
+ call cepis__buf_reset
+ lea LM_URL(%rbp), %rdi
+ mov CL_BASE_URL(%rbx), %rsi
+ call cepis__buf_appendz
+ test %eax, %eax
+ jnz .Llm_nomem
+ lea LM_URL(%rbp), %rdi
+ lea .Ls_csv_path(%rip), %rsi
+ call cepis__buf_appendz
+ test %eax, %eax
+ jnz .Llm_nomem
+ movq $0, LM_SENT(%rbp)
+ movq $0, LM_J(%rbp)
+.Llm_build:
+ mov LM_J(%rbp), %rax
+ cmp LM_CHUNK(%rbp), %rax
+ jae .Llm_request
+ add LM_IDX(%rbp), %rax
+ mov (%r12, %rax, 8), %rdi
+ lea LM_TMP(%rbp), %rsi
+ call cepis_normalize_cep
+ test %eax, %eax
+ jnz .Llm_build_next
+ cmpq $0, LM_SENT(%rbp)
+ je .Llm_build_first
+ lea LM_URL(%rbp), %rdi
+ mov $',', %esi
+ call cepis__buf_appendc
+ test %eax, %eax
+ jnz .Llm_nomem
+.Llm_build_first:
+ lea LM_URL(%rbp), %rdi
+ lea LM_TMP(%rbp), %rsi
+ call cepis__buf_appendz
+ test %eax, %eax
+ jnz .Llm_nomem
+ mov LM_J(%rbp), %rax
+ add LM_IDX(%rbp), %rax
+ mov LM_MAP(%rbp), %rcx
+ mov LM_SENT(%rbp), %rdx
+ mov %rax, (%rcx, %rdx, 8)
+ incq LM_SENT(%rbp)
+.Llm_build_next:
+ incq LM_J(%rbp)
+ jmp .Llm_build
+.Llm_request:
+ cmpq $0, LM_SENT(%rbp)
+ je .Llm_next_chunk
+ lea LM_BODY(%rbp), %rdi
+ call cepis__buf_reset
+ mov %rbx, %rdi
+ mov LM_URL(%rbp), %rsi
+ xor %edx, %edx
+ lea LM_STATUS(%rbp), %rcx
+ lea LM_BODY(%rbp), %r8
+ mov %r15, %r9
+ call cepis__http_get
+ test %eax, %eax
+ jnz .Llm_fail
+ cmpl $200, LM_STATUS(%rbp)
+ jne .Llm_badstatus
+ mov LM_BODY(%rbp), %rdi
+ test %rdi, %rdi
+ jz .Llm_badstatus
+ lea LM_ROWS(%rbp), %rsi
+ lea LM_NROWS(%rbp), %rdx
+ call cepis__csv_addresses
+ test %eax, %eax
+ jnz .Llm_fail
+ movq $0, LM_K(%rbp)
+.Llm_assign:
+ mov LM_K(%rbp), %rax
+ cmp LM_SENT(%rbp), %rax
+ jae .Llm_drop_extra
+ cmp LM_NROWS(%rbp), %rax
+ jae .Llm_drop_extra
+ mov LM_ROWS(%rbp), %rcx
+ mov (%rcx, %rax, 8), %rdx
+ movq $0, (%rcx, %rax, 8)
+ mov LM_MAP(%rbp), %rcx
+ mov (%rcx, %rax, 8), %rcx
+ mov (%r14), %rsi
+ mov %rdx, (%rsi, %rcx, 8)
+ incq LM_K(%rbp)
+ jmp .Llm_assign
+.Llm_drop_extra:
+ mov LM_ROWS(%rbp), %rdi
+ test %rdi, %rdi
+ jz .Llm_free_map
+ mov LM_NROWS(%rbp), %rsi
+ call cepis_address_list_free
+ movq $0, LM_ROWS(%rbp)
+ movq $0, LM_NROWS(%rbp)
+.Llm_free_map:
+ mov LM_MAP(%rbp), %rdi
+ call free@PLT
+ movq $0, LM_MAP(%rbp)
+.Llm_next_chunk:
+ mov LM_MAP(%rbp), %rdi
+ test %rdi, %rdi
+ jz .Llm_advance
+ call free@PLT
+ movq $0, LM_MAP(%rbp)
+.Llm_advance:
+ mov LM_CHUNK(%rbp), %rax
+ add %rax, LM_IDX(%rbp)
+ jmp .Llm_chunk
+.Llm_done:
+ lea LM_URL(%rbp), %rdi
+ call cepis__buf_free
+ lea LM_BODY(%rbp), %rdi
+ call cepis__buf_free
+ xor %eax, %eax
+ EPILOGUE
+ ret
+.Llm_badstatus:
+ mov %r15, %rdi
+ mov $CEPIS_ERR_INVALID_RESPONSE, %esi
+ lea .Lfmt_status(%rip), %rdx
+ mov LM_STATUS(%rbp), %ecx
+ mov LM_URL(%rbp), %r8
+ call cepis__err_set
+ mov $CEPIS_ERR_INVALID_RESPONSE, %eax
+.Llm_fail:
+ mov %eax, %r12d
+ mov LM_ROWS(%rbp), %rdi
+ test %rdi, %rdi
+ jz .Llm_fail_map
+ mov LM_NROWS(%rbp), %rsi
+ call cepis_address_list_free
+ movq $0, LM_ROWS(%rbp)
+.Llm_fail_map:
+ mov LM_MAP(%rbp), %rdi
+ test %rdi, %rdi
+ jz .Llm_fail_bufs
+ call free@PLT
+ movq $0, LM_MAP(%rbp)
+.Llm_fail_bufs:
+ lea LM_URL(%rbp), %rdi
+ call cepis__buf_free
+ lea LM_BODY(%rbp), %rdi
+ call cepis__buf_free
+ mov (%r14), %rdi
+ mov %r13, %rsi
+ call cepis_address_list_free
+ movq $0, (%r14)
+ mov %r12d, %eax
+ EPILOGUE
+ ret
+.Llm_nomem:
+ mov $CEPIS_ERR_NOMEM, %eax
+ jmp .Llm_fail
+.Llm_nomem_bare:
+ mov $CEPIS_ERR_NOMEM, %eax
+ EPILOGUE
+ ret
+.Llm_usage:
+ mov $CEPIS_ERR_USAGE, %eax
+ EPILOGUE
+ ret
+ENDFUNC cepis_lookup_many
+
+ .section .rodata
+.Ls_version: .asciz "0.1.0"
+.Ls_default_url: .asciz "https://cep.is"
+.Ls_default_ua: .asciz "cepis-asm/0.1.0 (+https://cep.is)"
+.Ls_health_path: .asciz "/health"
+.Ls_csv_path: .asciz "/csv?ceps="
+.Ls_mensagem: .asciz "mensagem"
+.Ls_rejected: .asciz "rejected by the API"
+.Ls_nullstr: .asciz "(null)"
+.Ls_unknown: .asciz "unknown error"
+.Lfmt_notfound: .asciz "CEP %s does not exist in the DNE database"
+.Lfmt_badcep: .asciz "CEP %s rejected: %s"
+.Lfmt_notdigits: .asciz "CEP must be 8 digits, got \"%s\""
+.Lfmt_badjson: .asciz "unparseable response from %s"
+.Lfmt_status: .asciz "unexpected status %d from %s"
+
+.Le_ok: .asciz "ok"
+.Le_invalid: .asciz "invalid CEP"
+.Le_notfound: .asciz "CEP not found"
+.Le_rate: .asciz "rate limited"
+.Le_server: .asciz "server error"
+.Le_network: .asciz "network error"
+.Le_badresp: .asciz "invalid response"
+.Le_nomem: .asciz "out of memory"
+.Le_usage: .asciz "invalid argument"
+
+ .section .data.rel.ro,"aw",@progbits
+ .p2align 3
+cepis__errnames:
+ .quad .Le_ok, .Le_invalid, .Le_notfound, .Le_rate, .Le_server
+ .quad .Le_network, .Le_badresp, .Le_nomem, .Le_usage
+
+ .section .rodata
+ .p2align 3
+.Ld_timeout: .double 10.0
+.Ld_backoff_base: .double 0.5
+.Ld_backoff_max: .double 8.0
+
+ .data
+ .p2align 3
+ .globl cepis__default_client
+ .hidden cepis__default_client
+cepis__default_client:
+ .quad 0
+cepis__seed_counter:
+ .quad 0
+
+ .section .note.GNU-stack,"",@progbits