00001 /*===-- runtime/crt_vstack.c ----------------------------------------------=== 00002 * 00003 * This file is distributed under the MIT license. See LICENSE.txt for details. 00004 * 00005 * Copyright (C) 2009, Stephen Wilson 00006 * 00007 *===----------------------------------------------------------------------===*/ 00008 00009 #include "comma/runtime/crt_vstack.h" 00010 00011 #include <stddef.h> 00012 #include <stdlib.h> 00013 #include <string.h> 00014 00015 /* 00016 * The vstack is represented as a singly linked list of vstack_entry structures. 00017 */ 00018 struct vstack_entry { 00019 struct vstack_entry *prev; 00020 char data[]; 00021 }; 00022 typedef struct vstack_entry *vstack_entry_t; 00023 00024 /* 00025 * The externally visible stack pointer. This value is set to the address of a 00026 * vstack_entry's data member, thus giving Comma code access to the pushed data. 00027 */ 00028 char *_comma_vstack = 0; 00029 00030 /* 00031 * Returns the top-most element from the vstack. 00032 */ 00033 static inline vstack_entry_t get_vstack_entry() 00034 { 00035 vstack_entry_t res; 00036 res = (vstack_entry_t)(_comma_vstack - offsetof(struct vstack_entry, data)); 00037 return res; 00038 } 00039 00040 /* 00041 * Sets the top-most entry of the vstack. 00042 */ 00043 static inline void set_vstack_entry(vstack_entry_t entry) 00044 { 00045 _comma_vstack = (char*)entry->data; 00046 } 00047 00048 /* 00049 * Public routine implementations. 00050 */ 00051 void _comma_vstack_alloc(int32_t size) 00052 { 00053 vstack_entry_t entry = malloc(sizeof(struct vstack_entry) + size); 00054 00055 entry->prev = get_vstack_entry(); 00056 set_vstack_entry(entry); 00057 } 00058 00059 void _comma_vstack_push(void *data, int32_t size) 00060 { 00061 vstack_entry_t entry = malloc(sizeof(struct vstack_entry) + size); 00062 00063 entry->prev = get_vstack_entry(); 00064 memcpy(entry->data, data, size); 00065 set_vstack_entry(entry); 00066 } 00067 00068 void _comma_vstack_pop() 00069 { 00070 vstack_entry_t entry = get_vstack_entry(); 00071 set_vstack_entry(entry->prev); 00072 free(entry); 00073 }