2 * Copyright (C) 2009 Behdad Esfahbod
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library, in a file named COPYING; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA
32 /* Glib array types */
45 #define LINE_SIZE 2048 /* Size of largest example line in BidiTest */
46 #define ARRAY_CHUNK_SIZE 32
47 int_array_t *new_int_array()
49 int_array_t *arr = (int_array_t*)malloc(sizeof(int_array_t));
51 arr->capacity = ARRAY_CHUNK_SIZE;
52 arr->data = (int*)malloc(arr->capacity * sizeof(int));
57 void int_array_add(int_array_t *arr, int val)
59 if (arr->len == arr->capacity)
61 arr->capacity += ARRAY_CHUNK_SIZE;
62 arr->data = (int*)realloc(arr->data, arr->capacity*sizeof(int));
64 arr->data[arr->len++] = val;
67 int *int_array_free(int_array_t *arr, int free_data)
69 int *data = arr->data;
78 char_array_t *new_char_array()
80 char_array_t *arr = (char_array_t*)malloc(sizeof(char_array_t));
82 arr->capacity = ARRAY_CHUNK_SIZE;
83 arr->data = (char*)malloc(arr->capacity);
88 void char_array_add(char_array_t *arr, char val)
90 if (arr->len == arr->capacity)
92 arr->capacity += ARRAY_CHUNK_SIZE;
93 arr->data = (char*)realloc(arr->data, arr->capacity * sizeof(char));
95 arr->data[arr->len++] = val;
98 char *char_array_free(char_array_t *arr, int free_data)
100 char *data = arr->data;
109 static void die(const char *fmt, ...)
114 vfprintf(stderr, fmt, ap);
118 static FriBidiCharType
119 parse_char_type (const char *s, int len)
121 #define MATCH(name, value) \
122 if (!strncmp (name, s, len) && name[len] == '\0') return value;
124 MATCH ("L", FRIBIDI_TYPE_LTR);
125 MATCH ("R", FRIBIDI_TYPE_RTL);
126 MATCH ("AL", FRIBIDI_TYPE_AL);
127 MATCH ("EN", FRIBIDI_TYPE_EN);
128 MATCH ("AN", FRIBIDI_TYPE_AN);
129 MATCH ("ES", FRIBIDI_TYPE_ES);
130 MATCH ("ET", FRIBIDI_TYPE_ET);
131 MATCH ("CS", FRIBIDI_TYPE_CS);
132 MATCH ("NSM", FRIBIDI_TYPE_NSM);
133 MATCH ("BN", FRIBIDI_TYPE_BN);
134 MATCH ("B", FRIBIDI_TYPE_BS);
135 MATCH ("S", FRIBIDI_TYPE_SS);
136 MATCH ("WS", FRIBIDI_TYPE_WS);
137 MATCH ("ON", FRIBIDI_TYPE_ON);
138 MATCH ("LRE", FRIBIDI_TYPE_LRE);
139 MATCH ("RLE", FRIBIDI_TYPE_RLE);
140 MATCH ("LRO", FRIBIDI_TYPE_LRO);
141 MATCH ("RLO", FRIBIDI_TYPE_RLO);
142 MATCH ("PDF", FRIBIDI_TYPE_PDF);
143 MATCH ("LRI", FRIBIDI_TYPE_LRI);
144 MATCH ("RLI", FRIBIDI_TYPE_RLI);
145 MATCH ("FSI", FRIBIDI_TYPE_FSI);
146 MATCH ("PDI", FRIBIDI_TYPE_PDI);
148 die("Oops. I shouldn't reach here!\n");
152 static FriBidiLevel *
153 parse_levels_line (const char *line,
156 char_array_t *levels;
158 if (!strncmp (line, "@Levels:", 8))
161 levels = new_char_array ();
169 l = strtol (line, &end, 10);
170 if (errno != EINVAL && line != end)
172 char_array_add (levels, l);
177 while (isspace (*line))
182 char_array_add (levels, -1);
190 die("Oops. I shouldn't be here!\n");
194 return (FriBidiLevel *) char_array_free(levels, FALSE);
197 static FriBidiStrIndex *
198 parse_reorder_line (const char *line,
199 FriBidiStrIndex *len)
205 if (!strncmp (line, "@Reorder:", 9))
208 map = new_int_array ();
210 for(; errno = 0, l = strtol (line, &end, 10), line != end && errno != EINVAL; line = end) {
211 int_array_add (map, l);
215 return (FriBidiStrIndex *) int_array_free (map, FALSE);
218 static FriBidiCharType *
219 parse_test_line (const char *line,
220 FriBidiStrIndex *len,
227 types = new_int_array();
230 while (isspace (*line))
233 while (isalpha (*end))
238 c = parse_char_type (line, end - line);
239 int_array_add (types, c);
246 *base_dir_flags = strtol (line, NULL, 10);
249 return (FriBidiCharType *) int_array_free (types, FALSE);
253 main (int argc, char **argv)
256 char line[LINE_SIZE];
257 FriBidiStrIndex *expected_ltor = NULL;
258 FriBidiStrIndex expected_ltor_len = 0;
259 FriBidiStrIndex *ltor = NULL;
260 FriBidiStrIndex ltor_len = 0;
261 FriBidiCharType *types = NULL;
262 FriBidiStrIndex types_len = 0;
263 FriBidiLevel *expected_levels = NULL;
264 FriBidiLevel expected_levels_len = 0;
265 FriBidiLevel *levels = NULL;
266 FriBidiStrIndex levels_len = 0;
267 int base_dir_flags, base_dir_mode;
272 const char *filename;
276 die ("usage: %s [--debug] test-file-name\n", argv[0]);
279 if (!strcmp (argv[next_arg], "--debug")) {
284 filename = argv[next_arg++];
286 channel = fopen(filename, "r");
288 die ("Failed opening %s\n", filename);
290 while (!feof(channel)) {
291 fgets(line, LINE_SIZE, channel);
292 int len = strlen(line);
293 if (len == LINE_SIZE-1)
294 die("LINE_SIZE too small at line %d!\n", line_no);
303 if (!strncmp (line, "@Reorder:", 9)) {
304 free (expected_ltor);
305 expected_ltor = parse_reorder_line (line, &expected_ltor_len);
308 if (!strncmp (line, "@Levels:", 8)) {
309 free (expected_levels);
310 expected_levels = parse_levels_line (line, &expected_levels_len);
318 types = parse_test_line (line, &types_len, &base_dir_flags);
321 levels = malloc (sizeof (FriBidiLevel) * types_len);
322 levels_len = types_len;
325 ltor = malloc (sizeof (FriBidiStrIndex) * types_len);
328 for (base_dir_mode = 0; base_dir_mode < 3; base_dir_mode++) {
329 FriBidiParType base_dir;
333 if ((base_dir_flags & (1<<base_dir_mode)) == 0)
338 switch (base_dir_mode) {
339 case 0: base_dir = FRIBIDI_PAR_ON; break;
340 case 1: base_dir = FRIBIDI_PAR_LTR; break;
341 case 2: base_dir = FRIBIDI_PAR_RTL; break;
344 if (fribidi_get_par_embedding_levels_ex (types,
345 NULL, /* Brackets are not used in the BidiTest.txt file */
351 for (i = 0; i < types_len; i++)
354 if (fribidi_reorder_line (0 /*FRIBIDI_FLAG_REORDER_NSM*/,
363 for (i = 0; i < types_len; i++)
364 if (!FRIBIDI_IS_EXPLICIT_OR_BN (types[ltor[i]]))
370 if (levels_len != expected_levels_len)
373 for (i = 0; i < levels_len; i++)
374 if (levels[i] != expected_levels[i] &&
375 expected_levels[i] != (FriBidiLevel) -1) {
380 if (ltor_len != expected_ltor_len)
383 for (i = 0; i < ltor_len; i++)
384 if (ltor[i] != expected_ltor[i]) {
393 fprintf (stderr, "failure on line %d\n", line_no);
394 fprintf (stderr, "input is: %s\n", line);
395 fprintf (stderr, "base dir: %s\n",
396 base_dir_mode==0 ? "auto"
397 : base_dir_mode==1 ? "LTR" : "RTL");
399 fprintf (stderr, "expected levels:");
400 for (i = 0; i < expected_levels_len; i++)
401 if (expected_levels[i] == (FriBidiLevel) -1)
402 fprintf (stderr," x");
404 fprintf (stderr, " %d", expected_levels[i]);
405 fprintf (stderr, "\n");
406 fprintf (stderr, "returned levels:");
407 for (i = 0; i < levels_len; i++)
408 fprintf (stderr, " %d", levels[i]);
409 fprintf (stderr, "\n");
411 fprintf (stderr, "expected order:");
412 for (i = 0; i < expected_ltor_len; i++)
413 fprintf (stderr, " %d", expected_ltor[i]);
414 fprintf (stderr, "\n");
415 fprintf (stderr, "returned order:");
416 for (i = 0; i < ltor_len; i++)
417 fprintf (stderr, " %d", ltor[i]);
418 fprintf (stderr, "\n");
422 FriBidiParType base_dir;
424 fribidi_set_debug (1);
426 switch (base_dir_mode) {
427 case 0: base_dir = FRIBIDI_PAR_ON; break;
428 case 1: base_dir = FRIBIDI_PAR_LTR; break;
429 case 2: base_dir = FRIBIDI_PAR_RTL; break;
432 if (fribidi_get_par_embedding_levels_ex (types,
433 NULL, /* No bracket types */
439 fribidi_set_debug (0);
442 fprintf (stderr, "\n");
449 free (expected_ltor);
450 free (expected_levels);
455 fprintf (stderr, "%d errors out of %d total tests\n", numerrs, numtests);
457 printf("No errors found! :-)\n");