1// This file is manually written. It tries to match exactly the same language interface
2// between Cogent and C.
3
4// Simplifications made:
5// 1. Multiple arguments to functions are allowed
6// 2. Not using bool_t type in cogent-defns.h
7// 3. Using NULLable pointer instead of variant type
8// 4. Using break in a for-loop
9
10
11#include <stdio.h>
12#include <string.h>
13#include <stdint.h>
14#include <stddef.h>
15#include <cogent-defns.h>
16
17typedef void *SysState;
18
19// *****************************************************************
20//   Cogent part.
21// *****************************************************************
22
23struct get_block_ret {
24  SysState *p1;
25  char *p2;
26};
27typedef struct get_block_ret get_block_ret_t;
28
29struct Stuff {
30  u32 a;
31  u32 b;
32  u32 c;
33};
34typedef struct Stuff Stuff_t;
35
36struct Entry {
37  u32 len;
38  Stuff_t stuff;
39  char* name;
40};
41typedef struct Entry Entry_t;
42
43
44get_block_ret_t get_block (SysState);
45Entry_t *get_entry_at_offset (char*, u64);
46int is_entry (char*, Entry_t*);
47int cstring_cmp(char*, char*);
48Stuff_t *stuff_ptr(Entry_t *);
49
50
51struct findStuff_ret {
52  SysState *p1;
53  Stuff_t *p2;
54};
55typedef struct findStuff_ret findStuff_ret_t;
56
57findStuff_ret_t findStuff (SysState *sys, char *name) {
58  get_block_ret_t ret_block = get_block(sys);
59  sys = ret_block.p1;
60  char *blk = ret_block.p2;
61
62  u64 offset = 0;
63  for (;;) {
64    Entry_t *e = get_entry_at_offset (blk, offset);
65    if (e->len == 0 || !is_entry(blk, e))
66      break;
67
68    if (cstring_cmp(name, e->name))
69      return (findStuff_ret_t){ .p1 = sys, .p2 = stuff_ptr(e) };
70    offset = offset + e->len;
71  }
72  return (findStuff_ret_t){ .p1 = sys, .p2 = NULL};
73}
74
75
76// *****************************************************************
77//   Below is the same as the main.ac file, with minor difference.
78// *****************************************************************
79
80
81#define SIZE 4096
82
83
84char block[SIZE]; // Contains Entry's jammed together; terminated by
85                  // len==0.
86
87
88get_block_ret_t get_block (SysState args) {
89  return (get_block_ret_t){ .p1 = args, .p2 = block };
90}
91
92Entry_t *get_entry_at_offset (char *block, u64 offset) {
93  return (Entry_t*)((uintptr_t)block + offset);
94}
95
96int is_entry (char *block, Entry_t *e) {
97  return ((uintptr_t)e - (uintptr_t)block) < SIZE;
98}
99
100int cstring_cmp(char *s1, char *s2) {
101  return !strcmp(s1, s2);
102}
103
104Stuff_t *stuff_ptr(Entry_t *e) {
105  return &e->stuff;
106}
107
108int in_range(Entry_t *e, unsigned long nlen) {
109  unsigned long p;
110
111  p = (uintptr_t)e + offsetof(Entry_t, name) + nlen;
112
113  return (p - (uintptr_t)block) < SIZE;
114}
115
116/* Initialise our block of entries. */
117/* Not translated into Cogent. */
118void init(void) {
119  FILE *fp;
120  Entry_t *e;
121  int a, b, c, len;
122  char buf[80];
123
124  memset(block, 0, SIZE);
125
126  if ((fp = fopen("entries.txt", "r")) != NULL) {
127    e = (Entry_t *)block;
128    while (fscanf(fp, "%s%d%d%d\n", buf, &a, &b, &c) == 4) {
129      len = strlen(buf)+1;
130      if (!in_range(e, len)) {
131        break;
132      }
133      // Point to the next location
134      e->name = (char*)((uintptr_t)e + offsetof(Entry_t, name) + sizeof(char*));
135      strcpy(e->name, buf);
136      e->stuff.a = a;
137      e->stuff.b = b;
138      e->stuff.c = c;
139      e->len = ((uintptr_t)e->name + len) - (uintptr_t)e;
140      e = (Entry_t *) ((uintptr_t)e + e->len);
141    }
142    fclose(fp);
143  }
144}
145
146int main(void){
147  struct findStuff_ret ret;
148  init();
149  char *str = {"wombat"};
150  ret = findStuff(NULL, str);
151  if (ret.p2) {
152    printf("Wombat's b is %d.\n", ret.p2->b);
153  } else {
154    printf("Wombat was not found.\n");
155  }
156  return 0;
157}
158
159
160