#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 FD_KEY -48 #define NF_NOTE -240 #define NF_NOTELEN 192 .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) jmp cepis__faixa_clear .Ler_out: ret ENDFUNC cepis__err_reset /* Blank the faixa of the error at %rdi, which must not be NULL. Leaf. */ FUNC cepis__faixa_clear movl $0, E_FAIXA+F_PRESENT(%rdi) movb $0, E_FAIXA+F_LOCALIDADE(%rdi) movb $0, E_FAIXA+F_UF(%rdi) movb $0, E_FAIXA+F_CEP_INI(%rdi) movb $0, E_FAIXA+F_CEP_FIM(%rdi) movq $0, E_FAIXA+F_CEPS(%rdi) ret ENDFUNC cepis__faixa_clear 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 /* * cepis__json_find(json, key) - point at the value of `key` in the object * starting at `json`, with leading whitespace already stepped over, or 0 when * the object has no such key. The value is not copied and not validated: the * caller decides what to do with whatever byte it finds there, which is how * a nested object is reached without a document tree. * * Scanning stops at the first key that matches and at the closing brace, so * calling it on an object embedded in a larger document is safe. */ FUNC cepis__json_find PROLOGUE 24 mov %rsi, %r13 movq $0, FD_KEY(%rbp) call cepis__js_ws mov %rax, %r12 cmpb $'{', (%r12) jne .Lfd_none lea 1(%r12), %rdi call cepis__js_ws mov %rax, %r12 cmpb $'}', (%r12) je .Lfd_none .Lfd_pair: cmpb $'"', (%r12) jne .Lfd_none mov %r12, %rdi lea FD_KEY(%rbp), %rsi call cepis__js_string test %rax, %rax jz .Lfd_none mov %rax, %rdi call cepis__js_ws mov %rax, %r12 cmpb $':', (%r12) jne .Lfd_none lea 1(%r12), %rdi call cepis__js_ws mov %rax, %r12 mov FD_KEY(%rbp), %rdi mov %r13, %rsi call strcmp@PLT test %eax, %eax jz .Lfd_hit mov %r12, %rdi call cepis__js_skip test %rax, %rax jz .Lfd_none mov %rax, %r12 mov FD_KEY(%rbp), %rdi call free@PLT movq $0, FD_KEY(%rbp) mov %r12, %rdi call cepis__js_ws mov %rax, %r12 cmpb $',', (%r12) jne .Lfd_none lea 1(%r12), %rdi call cepis__js_ws mov %rax, %r12 jmp .Lfd_pair .Lfd_hit: mov FD_KEY(%rbp), %rdi call free@PLT movq $0, FD_KEY(%rbp) mov %r12, %rax EPILOGUE ret .Lfd_none: mov FD_KEY(%rbp), %rdi test %rdi, %rdi jz .Lfd_ret call free@PLT .Lfd_ret: xor %eax, %eax EPILOGUE ret ENDFUNC cepis__json_find /* * cepis__json_field(json, key) - the scalar value of `key` as a fresh string * the caller frees, or 0 when the key is absent or holds an object or array. */ FUNC cepis__json_field PROLOGUE 24 movq $0, LOCAL0(%rbp) call cepis__json_find test %rax, %rax jz .Ljf_none movzbl (%rax), %ecx cmp $'{', %cl je .Ljf_none cmp $'[', %cl je .Ljf_none mov %rax, %rdi lea LOCAL0(%rbp), %rsi call cepis__js_scalar_text mov LOCAL0(%rbp), %rax EPILOGUE ret .Ljf_none: xor %eax, %eax EPILOGUE ret ENDFUNC cepis__json_field /* * cepis__faixa_str(obj, key, dst, size) - copy the scalar `key` of `obj` into * the fixed buffer `dst`, truncating rather than overflowing. `dst` is left * untouched when the key is absent, so the caller's blank stands. */ FUNC cepis__faixa_str PROLOGUE 8 mov %rdx, %r12 mov %rcx, %r13 call cepis__json_field test %rax, %rax jz .Lfx_out mov %rax, %rbx mov %r12, %rdi mov %r13, %rsi lea .Ls_pct_s(%rip), %rdx mov %rbx, %rcx xor %eax, %eax call snprintf@PLT mov %rbx, %rdi call free@PLT .Lfx_out: EPILOGUE ret ENDFUNC cepis__faixa_str /* * cepis__err_notfound(err, cep, body) - fill `err` for a 404. `err` may be * NULL and `body` may be NULL. * * The 404 body optionally carries a `faixa` object naming the municipality * that owns the band the CEP falls in. It is context for the failure, not an * address: the status stays CEPIS_ERR_NOT_FOUND either way. When the object * is missing, empty, or not an object, the message is byte-for-byte the one * this library has always produced. */ FUNC cepis__err_notfound PROLOGUE 216 test %rdi, %rdi jz .Lnf_ret mov %rdi, %rbx mov %rsi, %r14 mov %rdx, %r15 movb $0, NF_NOTE(%rbp) test %r15, %r15 jz .Lnf_emit mov %r15, %rdi lea .Ls_faixa(%rip), %rsi call cepis__json_find test %rax, %rax jz .Lnf_emit mov %rax, %r12 cmpb $'{', (%r12) jne .Lnf_emit mov %r12, %rdi lea .Ls_k_localidade(%rip), %rsi lea E_FAIXA+F_LOCALIDADE(%rbx), %rdx mov $F_LOCALIDADE_MAX, %ecx call cepis__faixa_str mov %r12, %rdi lea .Ls_k_uf(%rip), %rsi lea E_FAIXA+F_UF(%rbx), %rdx mov $F_UF_MAX, %ecx call cepis__faixa_str mov %r12, %rdi lea .Ls_k_cep_ini(%rip), %rsi lea E_FAIXA+F_CEP_INI(%rbx), %rdx mov $F_CEP_MAX, %ecx call cepis__faixa_str mov %r12, %rdi lea .Ls_k_cep_fim(%rip), %rsi lea E_FAIXA+F_CEP_FIM(%rbx), %rdx mov $F_CEP_MAX, %ecx call cepis__faixa_str mov %r12, %rdi lea .Ls_k_ceps(%rip), %rsi call cepis__json_find test %rax, %rax jz .Lnf_check movzbl (%rax), %ecx cmp $'{', %cl je .Lnf_check cmp $'[', %cl je .Lnf_check mov %rax, %rdi lea LOCAL0(%rbp), %rsi call cepis__js_number test %rax, %rax jz .Lnf_check cvttsd2si LOCAL0(%rbp), %rax mov %rax, E_FAIXA+F_CEPS(%rbx) .Lnf_check: cmpb $0, E_FAIXA+F_LOCALIDADE(%rbx) je .Lnf_clear movl $1, E_FAIXA+F_PRESENT(%rbx) lea NF_NOTE(%rbp), %rdi mov $NF_NOTELEN, %esi lea .Lfmt_faixa(%rip), %rdx lea E_FAIXA+F_LOCALIDADE(%rbx), %rcx lea E_FAIXA+F_UF(%rbx), %r8 mov E_FAIXA+F_CEPS(%rbx), %r9 lea E_FAIXA+F_CEP_FIM(%rbx), %rax push %rax lea E_FAIXA+F_CEP_INI(%rbx), %rax push %rax xor %eax, %eax call snprintf@PLT add $16, %rsp jmp .Lnf_emit .Lnf_clear: mov %rbx, %rdi call cepis__faixa_clear movb $0, NF_NOTE(%rbp) .Lnf_emit: mov %rbx, %rdi mov $CEPIS_ERR_NOT_FOUND, %esi lea .Lfmt_notfound(%rip), %rdx mov %r14, %rcx lea NF_NOTE(%rbp), %r8 call cepis__err_set .Lnf_ret: EPILOGUE ret ENDFUNC cepis__err_notfound 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 lea LK_TMP(%rbp), %rsi mov LK_BODY(%rbp), %rdx call cepis__err_notfound 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.2.0" .Ls_default_url: .asciz "https://cep.is" .Ls_default_ua: .asciz "cepis-asm/0.2.0 (+https://cep.is)" .Ls_health_path: .asciz "/health" .Ls_csv_path: .asciz "/csv?ceps=" .Ls_mensagem: .asciz "mensagem" .Ls_faixa: .asciz "faixa" .Ls_k_localidade: .asciz "localidade" .Ls_k_uf: .asciz "uf" .Ls_k_cep_ini: .asciz "cep_ini" .Ls_k_cep_fim: .asciz "cep_fim" .Ls_k_ceps: .asciz "ceps" .Ls_pct_s: .asciz "%s" .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%s" .Lfmt_faixa: .asciz " (%s/%s has %lld CEPs, the lowest %s and the highest %s)" .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