/* * Copyright (C) 2003, 2004, 2005, 2015 Filip Pizlo. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY FILIP PIZLO ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FILIP PIZLO OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gpc_internal.h" #include "tsf_format.h" gpc_proto_t *gpc_proto_create(uint32_t num_args) { gpc_proto_t *ret=malloc(sizeof(gpc_proto_t)); if (ret==NULL) { tsf_set_errno("Could not malloc gpc_proto_t"); return NULL; } ret->num_args=num_args; ret->stream=NULL; ret->size=0; return ret; } void gpc_proto_destroy(gpc_proto_t *proto) { if (proto->stream!=NULL) { free(proto->stream); } free(proto); } tsf_bool_t gpc_proto_reserve(gpc_proto_t *proto, uint32_t num_slots) { if (proto->stream==NULL) { proto->stream=malloc(sizeof(gpc_cell_t)*num_slots); if (proto->stream==NULL) { tsf_set_errno("Could not malloc gpc_cell_t array"); return tsf_false; } } else { gpc_cell_t *new_array= realloc(proto->stream, sizeof(gpc_cell_t) * (proto->size+num_slots)); if (new_array==NULL) { tsf_set_errno("Could not realloc gpc_cell_t array"); return tsf_false; } proto->stream=new_array; } return tsf_true; } tsf_bool_t gpc_proto_append(gpc_proto_t *proto, gpc_cell_t inst, ...) { va_list lst; uint32_t size=gpc_instruction_static_size(inst); va_start(lst,inst); if (size==UINT32_MAX) { gpc_cell_t len= va_arg(lst,gpc_cell_t); if (!gpc_proto_reserve(proto,2+len)) { return tsf_false; } proto->stream[proto->size++]=inst; proto->stream[proto->size++]=len; while (len-->0) { proto->stream[proto->size++]= va_arg(lst,gpc_cell_t); } return tsf_true; } if (!gpc_proto_reserve(proto,size)) { return tsf_false; } proto->stream[proto->size++]=inst; while (--size>0) { proto->stream[proto->size++]= va_arg(lst,gpc_cell_t); } return tsf_true; } tsf_bool_t gpc_proto_append_tableset_local_to_field(gpc_proto_t *proto, gpc_cell_t offset, gpc_cell_t num, const gpc_cell_t *args) { uint32_t i; if (!gpc_proto_reserve(proto,3+num)) { return tsf_false; } proto->stream[proto->size++]=GPC_I_TABLESET_LOCAL_TO_FIELD; proto->stream[proto->size++]=offset; proto->stream[proto->size++]=num; for (i=0;istream[proto->size++]=args[i]; } return tsf_true; } tsf_bool_t gpc_proto_append_tableset_field_to_field(gpc_proto_t *proto, gpc_cell_t dest_offset, gpc_cell_t src_offset, gpc_cell_t num, const gpc_cell_t *args) { uint32_t i; if (!gpc_proto_reserve(proto,4+num)) { return tsf_false; } proto->stream[proto->size++]=GPC_I_TABLESET_FIELD_TO_FIELD; proto->stream[proto->size++]=dest_offset; proto->stream[proto->size++]=src_offset; proto->stream[proto->size++]=num; for (i=0;istream[proto->size++]=args[i]; } return tsf_true; } tsf_bool_t gpc_proto_append_tablejump_local(gpc_proto_t *proto, gpc_cell_t num, const gpc_cell_t *args) { uint32_t i; if (!gpc_proto_reserve(proto,2+num)) { return tsf_false; } proto->stream[proto->size++]=GPC_I_TABLEJUMP_LOCAL; proto->stream[proto->size++]=num; for (i=0;istream[proto->size++]=args[i]; } return tsf_true; } tsf_bool_t gpc_proto_append_tablejump_field(gpc_proto_t *proto, gpc_cell_t offset, gpc_cell_t num, const gpc_cell_t *args) { uint32_t i; if (!gpc_proto_reserve(proto,3+num)) { return tsf_false; } proto->stream[proto->size++]=GPC_I_TABLEJUMP_FIELD; proto->stream[proto->size++]=offset; proto->stream[proto->size++]=num; for (i=0;istream[proto->size++]=args[i]; } return tsf_true; } void gpc_proto_print(gpc_proto_t *proto, FILE *out) { uint32_t i; for (i = 0; i < proto->size;) { uint32_t size = gpc_instruction_size(proto->stream + i); if (proto->stream[i] == GPC_I_LABEL) { fprintf(out, fui64 ":", (uint64_t)proto->stream[i + 1]); } else { uint32_t j; const char *name= gpc_instruction_to_string(proto->stream[i]); if (strlen(name) < 35) { for (j = 0; j < 35 - strlen(name); ++j) { fprintf(out, " "); } } fprintf(out, "%s", name); for (j = 1; j < size; ++j) { fprintf(out, "\t" fui64, (uint64_t)proto->stream[i + j]); } } fprintf(out, "\n"); i += size; } }