~ubuntu-branches/ubuntu/intrepid/blender/intrepid-updates

« back to all changes in this revision

Viewing changes to extern/verse/dist/verse_ms.c

  • Committer: Bazaar Package Importer
  • Author(s): Cyril Brulebois
  • Date: 2008-08-08 02:45:40 UTC
  • mfrom: (12.1.14 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080808024540-kkjp7ekfivzhuw3l
Tags: 2.46+dfsg-4
* Fix python syntax warning in import_dxf.py, which led to nasty output
  in installation/upgrade logs during byte-compilation, using a patch
  provided by the script author (Closes: #492280):
   - debian/patches/45_fix_python_syntax_warning

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * A helper library to send and parse master server pings. See the relevant
 
3
 * header for details.
 
4
 * 
 
5
 * This code was written in 2006 by Emil Brink. It is released as public domain.
 
6
*/
 
7
 
 
8
#include <ctype.h>
 
9
#include <stdio.h>
 
10
#include <stdlib.h>
 
11
#include <string.h>
 
12
 
 
13
#include "verse.h"
 
14
#include "verse_ms.h"
 
15
 
 
16
/* Build and send a MS:GET packet. */
 
17
void verse_ms_get_send(const char *address, int fields, const char *tags)
 
18
{
 
19
        char    req[128];
 
20
 
 
21
        strcpy(req, "MS:GET IP=");
 
22
        if(fields & VERSE_MS_FIELD_DESCRIPTION)
 
23
                strcat(req, "DE");
 
24
        if(tags != NULL)
 
25
        {
 
26
                strcat(req, " TA=");
 
27
                strcat(req, tags);
 
28
        }
 
29
        verse_send_ping(address, req);
 
30
}
 
31
 
 
32
/* Skip assign, i.e. "NAME=" string, at <msg>. Stores name into <put>, and then updates
 
33
 * it. Returns NULL on parse error, in which case the <put> pointer is not advanced.
 
34
*/
 
35
static const char * skip_assign(char **put, const char *msg)
 
36
{
 
37
        if(isalpha(*msg))
 
38
        {
 
39
                char    *p = put != NULL ? *put : NULL;
 
40
 
 
41
                if(p != NULL)
 
42
                        *p++ = *msg;
 
43
                msg++;
 
44
                while(*msg && (isalnum(*msg) || *msg == '_'))
 
45
                {
 
46
                        if(p != NULL)
 
47
                                *p++ = *msg;
 
48
                        msg++;
 
49
                }
 
50
                if(*msg == '=')
 
51
                {
 
52
                        if(p != NULL)
 
53
                                *p++ = '\0';
 
54
                        if(put != NULL)
 
55
                                *put = p;
 
56
                        return msg + 1;
 
57
                }
 
58
        }
 
59
        return NULL;
 
60
}
 
61
 
 
62
/** Skip value at <msg>, optionally storing de-quoted version through <put>,
 
63
 * which is advanced. Returns NULL on parse error, without updating <put>.
 
64
*/
 
65
static const char * skip_value(char **put, const char *msg)
 
66
{
 
67
        char    *p = (put != NULL) ? *put : NULL;
 
68
 
 
69
        if(*msg == '"')
 
70
        {
 
71
                msg++;
 
72
                while(*msg != '\0' && *msg != '"')
 
73
                {
 
74
                        if(*msg == '\\')
 
75
                        {
 
76
                                if(msg[1] != '\0')
 
77
                                        msg++;
 
78
                                else
 
79
                                        return NULL;
 
80
                        }
 
81
                        if(p != NULL)
 
82
                                *p++ = *msg;
 
83
                        msg++;
 
84
                }
 
85
                if(*msg == '"')
 
86
                {
 
87
                        if(p != NULL)
 
88
                                *p++ = '\0';
 
89
                        if(put != NULL)
 
90
                                *put = p;
 
91
                        msg++;
 
92
                        if(*msg == '\0' || isspace(*msg))
 
93
                                return msg;
 
94
                }
 
95
                return NULL;
 
96
        }
 
97
        while(*msg && !isspace(*msg))
 
98
        {
 
99
                if(*msg == '"')
 
100
                        return NULL;
 
101
                if(p != NULL)
 
102
                        *p++ = *msg;
 
103
                msg++;
 
104
        }
 
105
        if(p != NULL)
 
106
                *p++ = '\0';
 
107
        if(put != NULL)
 
108
                *put = p;
 
109
        return msg;
 
110
}
 
111
 
 
112
static const char * put_field(VMSField *field, char **put, const char *src)
 
113
{
 
114
        const char      *ptr;
 
115
        char            *base = *put;
 
116
 
 
117
        if((ptr = skip_assign(put, src)) != NULL && ptr - src > 1)
 
118
        {
 
119
                field->name = base;
 
120
                src = ptr;
 
121
                base = *put;
 
122
                if((ptr = skip_value(put, src)) != NULL)
 
123
                {
 
124
                        field->value = base;
 
125
                        return ptr;
 
126
                }
 
127
        }
 
128
        return NULL;
 
129
}
 
130
 
 
131
static int cmp_fields(const void *a, const void *b)
 
132
{
 
133
        return strcmp(((const VMSField *) a)->name, ((const VMSField *) b)->name);
 
134
}
 
135
 
 
136
VMSServer ** verse_ms_list_parse(const char *msg)
 
137
{
 
138
        const char      *word[384];     /* Takes quite a lot of stack space. */
 
139
        const char      *ptr;
 
140
        char            *put;
 
141
        size_t          num_word = 0, i, j, num_ip = 0, num_field, space = 0;
 
142
        VMSServer               **desc, *next;
 
143
        VMSField        *field;
 
144
 
 
145
        if(strncmp(msg, "MS:LIST", 7) == 0)
 
146
                msg += 7;
 
147
        if(*msg != ' ')
 
148
                return NULL;
 
149
 
 
150
        /* Step one: split the string into words, at whitespace. Split is aware
 
151
         * of quoting rules for value assignment, this is crucial. This split is
 
152
         * non-invasive, meaning each "word" will be a suffix.
 
153
        */
 
154
        while(*msg)
 
155
        {
 
156
                while(isspace(*msg))
 
157
                        msg++;
 
158
                ptr = skip_assign(NULL, msg);
 
159
                if(ptr != NULL)
 
160
                {
 
161
                        space += ptr - msg;
 
162
                        word[num_word++] = msg;
 
163
                        msg = ptr;
 
164
                        ptr = skip_value(NULL, msg);
 
165
                        if(ptr == NULL)
 
166
                        {
 
167
                                fprintf(stderr, "Parse error\n");
 
168
                                return NULL;
 
169
                        }
 
170
                        space += ptr - msg + 1;
 
171
                        msg = ptr;
 
172
                }
 
173
                else if(*msg != '\0')
 
174
                {
 
175
                        fprintf(stderr, "Parse error\n");
 
176
                        return NULL;
 
177
                }
 
178
        }
 
179
        /* Now, count how many words begin with "IP=". */
 
180
        for(i = 0; i < num_word; i++)
 
181
        {
 
182
                if(strncmp(word[i], "IP=", 3) == 0)
 
183
                        num_ip++;
 
184
        }
 
185
/*      printf("found %u IPs, %u bytes\n", num_ip, space);
 
186
        printf("%u IP and %u words -> %u fields total\n", num_ip, num_word, num_word - num_ip);
 
187
*/      num_field = num_word - num_ip;
 
188
        /* Allocate the descriptions. */
 
189
/*      printf("allocating %u bytes\n", (num_ip + 1) * (sizeof *desc) + num_ip * sizeof **desc + num_field * sizeof (VMSField) + space);
 
190
        printf(" %u for pointers, %u for structs, %u for fields, %u string\n",
 
191
               (num_ip + 1) * (sizeof *desc), num_ip * sizeof **desc, num_field * sizeof (VMSField), space);
 
192
*/      desc = malloc((num_ip + 1) * (sizeof *desc) + num_ip * sizeof **desc + num_field * sizeof (VMSField) + space);
 
193
        next = (VMSServer *) (desc + (num_ip + 1));
 
194
/*      printf("desc store at %u\n", (char *) next - (char *) desc);*/
 
195
        field = (VMSField *) (next + num_ip);
 
196
/*      printf("field store at %u\n", (char *) field - (char *) desc);*/
 
197
        put  = (char *) (field + num_field);
 
198
/*      printf("string store at %u\n", put - (char *) desc);*/
 
199
        for(i = j = 0; i < num_word;)
 
200
        {
 
201
                if(strncmp(word[i], "IP=", 3) == 0)
 
202
                {
 
203
                        desc[j] = next;
 
204
                        next->ip = put;
 
205
                        ptr = skip_value(&put, word[i] + 3);
 
206
                        next->num_fields = 0;
 
207
                        next->field = field;
 
208
                        for(i++; i < num_word && strncmp(word[i], "IP=", 3) != 0; i++, next->num_fields++, field++)
 
209
                                put_field(&next->field[next->num_fields], &put, word[i]);
 
210
                        if(next->num_fields > 0)        /* Sort the fields, for binary search later. */
 
211
                                qsort(next->field, next->num_fields, sizeof *next->field, cmp_fields);
 
212
                        j++;
 
213
                        next++;
 
214
                }
 
215
                else
 
216
                        i++;
 
217
        }
 
218
        desc[j] = NULL;
 
219
        return desc;
 
220
}
 
221
 
 
222
/* A binary search, exploiting that the fields are sorted. */
 
223
static const VMSField * field_find(const VMSServer *ms, const char *name)
 
224
{
 
225
        int     lo, hi, mid, rel;
 
226
 
 
227
        if(ms == NULL || name == NULL)
 
228
                return NULL;
 
229
        lo = 0;
 
230
        hi = ms->num_fields;
 
231
        while(lo <= hi)
 
232
        {
 
233
                mid = (lo + hi) / 2;
 
234
                rel = strcmp(name, ms->field[mid].name);
 
235
                if(rel == 0)
 
236
                        return &ms->field[mid];
 
237
                if(rel < 0)
 
238
                        hi = mid - 1;
 
239
                else
 
240
                        lo = mid + 1;
 
241
        }
 
242
        return NULL;
 
243
}
 
244
 
 
245
int verse_ms_field_exists(const VMSServer *ms, const char *name)
 
246
{
 
247
        if(ms == NULL || name == NULL)
 
248
                return 0;
 
249
        return field_find(ms, name) != NULL;
 
250
}
 
251
 
 
252
const char * verse_ms_field_value(const VMSServer *ms, const char *name)
 
253
{
 
254
        const VMSField  *f;
 
255
 
 
256
        if((f = field_find(ms, name)) != NULL)
 
257
                return f->value;
 
258
        return NULL;
 
259
}
 
260
 
 
261
#if defined VERSE_MS_STANDALONE
 
262
 
 
263
int main(void)
 
264
{
 
265
        VMSServer       **servers = verse_ms_list_parse("MS:LIST IP=127.0.0.1:4951 DE=\"A test server, mainly for Eskil\" COOL=yes BACKUP=daily LANG=sv_SE "
 
266
                                                "IP=130.237.221.74 DE=\"Test server on a puny laptop\" COOL=yes DORKY=no OPEN=absolutely "
 
267
                                                "IP=127.0.0.1:5151 DE=\"This is a back slash: '\\\\', cool huh?\" "
 
268
                                                "IP=127.0.0.1:6676 DE=\"a quote looks like this: \\\"\"  IP=127.0.0.1:1122 ");
 
269
 
 
270
        if(servers != NULL)
 
271
        {
 
272
                int     i, j;
 
273
 
 
274
                printf("Server info:\n");
 
275
                for(i = 0; servers[i] != NULL; i++)
 
276
                {
 
277
                        printf("%u: IP=%s\n", i, servers[i]->ip);
 
278
                        for(j = 0; j < servers[i]->num_fields; j++)
 
279
                                printf(" %s='%s'\n", servers[i]->field[j].name, servers[i]->field[j].value);
 
280
                }
 
281
                free(servers);
 
282
        }
 
283
        return EXIT_SUCCESS;
 
284
}
 
285
 
 
286
#endif          /* VERSE_MS_STANDALONE */