first version of reading api source files
[lttv.git] / ltt / branches / poly / ltt / parser.c
1 /*
2
3 parser.c: Generate helper declarations and functions to trace events
4 from an event description file.
5
6 Copyright (C) 2002, Xianxiu Yang
7 Copyright (C) 2002, Michel Dagenais
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; version 2 of the License.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 /* This program reads the ".event" event definitions input files
23 specified as command line arguments and generates corresponding
24 ".c" and ".h" files required to trace such events in the kernel.
25
26 The program uses a very simple tokenizer, called from a hand written
27 recursive descent parser to fill a data structure describing the events.
28 The result is a sequence of events definitions which refer to type
29 definitions.
30
31 A table of named types is maintained to allow refering to types by name
32 when the same type is used at several places. Finally a sequence of
33 all types is maintained to facilitate the freeing of all type
34 information when the processing of an ".event" file is finished. */
35
36 #include <stdlib.h>
37 #include <string.h>
38 #include <stdio.h>
39 #include <stdarg.h>
40 #include <linux/errno.h>
41
42
43 #include "parser.h"
44
45
46 /*****************************************************************************
47 *Function name
48 * getSize : translate from string to integer
49 *Input params
50 * in : input file handle
51 *Return values
52 * size
53 *****************************************************************************/
54
55 int getSize(parse_file *in)
56 {
57 char *token;
58
59 token = getToken(in);
60 if(in->type == NUMBER) {
61 if(strcmp(token,"1") == 0) return 0;
62 else if(strcmp(token,"2") == 0) return 1;
63 else if(strcmp(token,"4") == 0) return 2;
64 else if(strcmp(token,"8") == 0) return 3;
65 }
66 else if(in->type == NAME) {
67 if(strcmp(token,"short") == 0) return 4;
68 else if(strcmp(token,"medium") == 0) return 5;
69 else if(strcmp(token,"long") == 0) return 6;
70 }
71 in->error(in,"incorrect size specification");
72 return -1;
73 }
74
75 /*****************************************************************************
76 *Function name
77 * error_callback : print out error info
78 *Input params
79 * in : input file handle
80 * msg : message to be printed
81 ****************************************************************************/
82
83 void error_callback(parse_file *in, char *msg)
84 {
85 if(in)
86 printf("Error in file %s, line %d: %s\n", in->name, in->lineno, msg);
87 else
88 printf("%s\n",msg);
89 exit(1);
90 }
91
92 /*****************************************************************************
93 *Function name
94 * memAlloc : allocate memory
95 *Input params
96 * size : required memory size
97 *return value
98 * void * : pointer to allocate memory or NULL
99 ****************************************************************************/
100
101 void * memAlloc(int size)
102 {
103 void *addr = malloc(size);
104 if(!addr){
105 printf("Failed to allocate memory");
106 exit(1);
107 }
108 return addr;
109 }
110
111 /*****************************************************************************
112 *Function name
113 * allocAndCopy : allocate memory and initialize it
114 *Input params
115 * str : string to be put in memory
116 *return value
117 * char * : pointer to allocate memory or NULL
118 ****************************************************************************/
119
120 char *allocAndCopy(char *str)
121 {
122 char *addr = (char *)memAlloc(strlen(str)+1);
123 strcpy(addr,str);
124 return addr;
125 }
126
127
128 /*****************************************************************************
129 *Function name
130 * parseEvent : generate event from event definition
131 *Input params
132 * in : input file handle
133 * ev : new event
134 *Output params
135 * ev : new event (parameters are passed to it)
136 ****************************************************************************/
137
138 void parseEvent(parse_file *in, event * ev, sequence * unnamed_types,
139 table * named_types)
140 {
141 char *token;
142 type_descriptor *t;
143
144 getLParenthesis(in);
145 token = getName(in);
146 ev->name = allocAndCopy(token);
147 getComa(in);
148
149 token = getQuotedString(in);
150 ev->description = allocAndCopy(token);
151
152 token = getToken(in); //token either is a ',' or a ')'
153 if(in->type == COMA) token = getName(in);
154 ungetToken(in);
155
156 /* We have a possibly empty list of fields, containing struct implied */
157 if((in->type == NAME && strcmp(token,"field") == 0) ||
158 in->type == RPARENTHESIS) {
159 /* Insert an unnamed struct type */
160 t = (type_descriptor *)memAlloc(sizeof(type_descriptor));
161 t->type_name = NULL;
162 t->type = STRUCT;
163 t->fmt = NULL;
164 if(in->type == NAME) parseFields(in,t, unnamed_types, named_types);
165 else if(in->type == RPARENTHESIS) sequence_init(&(t->fields));
166 sequence_push(unnamed_types,t);
167 ev->type = t;
168 }
169
170 /* Or a complete type declaration but it must be a struct */
171 else if(in->type == NAME){
172 ev->type = parseType(in,NULL, unnamed_types, named_types);
173 if(ev->type->type != STRUCT && ev->type->type != NONE) in->error(in,"type must be a struct");
174 }else in->error(in,"not a struct type");
175
176 getRParenthesis(in);
177 getSemiColon(in);
178 }
179
180 /*****************************************************************************
181 *Function name
182 * parseField : get field infomation from buffer
183 *Input params
184 * in : input file handle
185 * t : type descriptor
186 ****************************************************************************/
187
188 void parseFields(parse_file *in, type_descriptor *t, sequence * unnamed_types,
189 table * named_types)
190 {
191 char * token;
192 field *f;
193
194 sequence_init(&(t->fields));
195
196 token = getToken(in);
197 while(in->type == NAME && strcmp(token,"field") == 0) {
198 f = (field *)memAlloc(sizeof(field));
199 sequence_push(&(t->fields),f);
200
201 getLParenthesis(in);
202 f->name = (char *)allocAndCopy(getName(in));
203 getComa(in);
204 f->description = (char *)allocAndCopy(getQuotedString(in));
205 getComa(in);
206 f->type = parseType(in,NULL, unnamed_types, named_types);
207 getRParenthesis(in);
208
209 token = getToken(in);
210 if(in->type == COMA) token = getName(in);
211 else ungetToken(in); // no more fields, it must be a ')'
212 }
213
214 if(in->type == NAME && strcmp(token,"field") != 0)
215 in->error(in,"not a field");
216 }
217
218
219 /*****************************************************************************
220 *Function name
221 * parseType : get type information, type can be :
222 * Primitive:
223 * int(size,fmt); uint(size,fmt); float(size,fmt);
224 * string(fmt); enum(size,fmt,(label1,label2...))
225 * Compound:
226 * array(arraySize, type); sequence(lengthSize,type)
227 * struct(field(name,type,description)...)
228 * type name:
229 * type(name,type)
230 *Input params
231 * in : input file handle
232 * inType : a type descriptor
233 *Return values
234 * type_descriptor* : a type descriptor
235 ****************************************************************************/
236
237 type_descriptor *parseType(parse_file *in, type_descriptor *inType,
238 sequence * unnamed_types, table * named_types)
239 {
240 char *token, *car;
241 type_descriptor *t;
242
243 if(inType == NULL) {
244 t = (type_descriptor *) memAlloc(sizeof(type_descriptor));
245 t->type_name = NULL;
246 t->type = NONE;
247 t->fmt = NULL;
248 sequence_push(unnamed_types,t);
249 }
250 else t = inType;
251
252 token = getName(in);
253
254 if(strcmp(token,"struct") == 0) {
255 t->type = STRUCT;
256 getLParenthesis(in);
257 parseFields(in,t, unnamed_types, named_types);
258 getRParenthesis(in);
259 }
260 else if(strcmp(token,"array") == 0) {
261 t->type = ARRAY;
262 getLParenthesis(in);
263 t->size = getNumber(in);
264 getComa(in);
265 t->nested_type = parseType(in,NULL, unnamed_types, named_types);
266 getRParenthesis(in);
267 }
268 else if(strcmp(token,"sequence") == 0) {
269 t->type = SEQUENCE;
270 getLParenthesis(in);
271 t->size = getSize(in);
272 getComa(in);
273 t->nested_type = parseType(in,NULL, unnamed_types, named_types);
274 getRParenthesis(in);
275 }
276 else if(strcmp(token,"enum") == 0) {
277 t->type = ENUM;
278 sequence_init(&(t->labels));
279 getLParenthesis(in);
280 t->size = getSize(in);
281 getComa(in);
282 token = getToken(in);
283 if(in->type == QUOTEDSTRING){
284 t->fmt = allocAndCopy(token);
285 getComa(in);
286 }else ungetToken(in);
287 getLParenthesis(in);
288
289 token = getToken(in);
290 while(in->type != RPARENTHESIS) {
291 if(in->type != NAME) in->error(in,"Name token was expected");
292 car = allocAndCopy(token);
293 token = getToken(in);
294 if(in->type == COMA){
295 sequence_push(&(t->labels),allocAndCopy(car));
296 token = getName(in);
297 }else if(in->type == EQUAL){ //label followed by '=' and a number, e.x. label1 = 1,
298 car = appendString(car, token);
299 token = getToken(in);
300 if(in->type != NUMBER) in->error(in,"Number token was expected");
301 car = appendString(car, token);
302 sequence_push(&(t->labels),allocAndCopy(car));
303 token = getToken(in);
304 if(in->type == COMA) token = getName(in);
305 else ungetToken(in);
306 }else{
307 sequence_push(&(t->labels),allocAndCopy(car));
308 ungetToken(in);
309 }
310 }
311 getRParenthesis(in);
312 getRParenthesis(in);
313 }
314 else if(strcmp(token,"int") == 0) {
315 t->type = INT;
316 getLParenthesis(in);
317 t->size = getSize(in);
318 token = getToken(in);
319 if(in->type == COMA) {
320 token = getQuotedString(in);
321 t->fmt = allocAndCopy(token);
322 }
323 else ungetToken(in);
324 getRParenthesis(in);
325 }
326 else if(strcmp(token,"uint") == 0) {
327 t->type = UINT;
328 getLParenthesis(in);
329 t->size = getSize(in);
330 token = getToken(in);
331 if(in->type == COMA) {
332 token = getQuotedString(in);
333 t->fmt = allocAndCopy(token);
334 }
335 else ungetToken(in);
336 getRParenthesis(in);
337 }
338 else if(strcmp(token,"float") == 0) {
339 t->type = FLOAT;
340 getLParenthesis(in);
341 t->size = getSize(in);
342 token = getToken(in);
343 if(in->type == COMA) {
344 token = getQuotedString(in);
345 t->fmt = allocAndCopy(token);
346 }
347 else ungetToken(in);
348 getRParenthesis(in);
349 }
350 else if(strcmp(token,"string") == 0) {
351 t->type = STRING;
352 getLParenthesis(in);
353 token = getToken(in);
354 if(in->type == QUOTEDSTRING) t->fmt = allocAndCopy(token);
355 else ungetToken(in);
356 getRParenthesis(in);
357 }
358 else {
359 /* Must be a named type */
360 if(inType != NULL)
361 in->error(in,"Named type cannot refer to a named type");
362 else {
363 free(t);
364 sequence_pop(unnamed_types);
365 return(find_named_type(token, named_types));
366 }
367 }
368
369 return t;
370 }
371
372 /*****************************************************************************
373 *Function name
374 * find_named_type : find a named type from hash table
375 *Input params
376 * name : type name
377 *Return values
378 * type_descriptor * : a type descriptor
379 *****************************************************************************/
380
381 type_descriptor * find_named_type(char *name, table * named_types)
382 {
383 type_descriptor *t;
384
385 t = table_find(named_types,name);
386 if(t == NULL) {
387 t = (type_descriptor *)memAlloc(sizeof(type_descriptor));
388 t->type_name = allocAndCopy(name);
389 t->type = NONE;
390 t->fmt = NULL;
391 table_insert(named_types,allocAndCopy(name),t);
392 }
393 return t;
394 }
395
396 /*****************************************************************************
397 *Function name
398 * parseTypeDefinition : get type information from type definition
399 *Input params
400 * in : input file handle
401 *****************************************************************************/
402
403 void parseTypeDefinition(parse_file * in, sequence * unnamed_types,
404 table * named_types)
405 {
406 char *token;
407 type_descriptor *t;
408
409 getLParenthesis(in);
410 token = getName(in);
411 t = find_named_type(token, named_types);
412 getComa(in);
413
414 if(t->type != NONE) in->error(in,"redefinition of named type");
415 parseType(in,t, unnamed_types, named_types);
416
417 getRParenthesis(in);
418 getSemiColon(in);
419 }
420
421 /**************************************************************************
422 * Function :
423 * getComa, getName, getNumber, getLParenthesis, getRParenthesis, getEqual
424 * Description :
425 * Read a token from the input file, check its type, return it scontent.
426 *
427 * Parameters :
428 * in , input file handle.
429 *
430 * Return values :
431 * address of token content.
432 *
433 **************************************************************************/
434
435 char *getName(parse_file * in)
436 {
437 char *token;
438
439 token = getToken(in);
440 if(in->type != NAME) in->error(in,"Name token was expected");
441 return token;
442 }
443
444 int getNumber(parse_file * in)
445 {
446 char *token;
447
448 token = getToken(in);
449 if(in->type != NUMBER) in->error(in, "Number token was expected");
450 return atoi(token);
451 }
452
453 char *getComa(parse_file * in)
454 {
455 char *token;
456
457 token = getToken(in);
458 if(in->type != COMA) in->error(in, "Coma token was expected");
459 return token;
460 }
461
462 char *getLParenthesis(parse_file * in)
463 {
464 char *token;
465
466 token = getToken(in);
467 if(in->type != LPARENTHESIS) in->error(in, "Left parenthesis was expected");
468 return token;
469 }
470
471 char *getRParenthesis(parse_file * in)
472 {
473 char *token;
474
475 token = getToken(in);
476 if(in->type != RPARENTHESIS) in->error(in, "Right parenthesis was expected");
477 return token;
478 }
479
480 char *getQuotedString(parse_file * in)
481 {
482 char *token;
483
484 token = getToken(in);
485 if(in->type != QUOTEDSTRING) in->error(in, "quoted string was expected");
486 return token;
487 }
488
489 char * getSemiColon(parse_file *in)
490 {
491 char *token;
492
493 token = getToken(in);
494 if(in->type != SEMICOLON) in->error(in, "semicolon was expected");
495 return token;
496 }
497
498 char * getEqual(parse_file *in)
499 {
500 char *token;
501
502 token = getToken(in);
503 if(in->type != EQUAL) in->error(in, "equal was expected");
504 return token;
505 }
506
507 /******************************************************************
508 * Function :
509 * getToken, ungetToken
510 * Description :
511 * Read a token from the input file and return its type and content.
512 * Line numbers are accounted for and whitespace/comments are skipped.
513 *
514 * Parameters :
515 * in, input file handle.
516 *
517 * Return values :
518 * address of token content.
519 *
520 ******************************************************************/
521
522 void ungetToken(parse_file * in)
523 {
524 in->unget = 1;
525 }
526
527 char *getToken(parse_file * in)
528 {
529 FILE *fp = in->fp;
530 char car, car1;
531 int pos = 0, escaped;
532
533 if(in->unget == 1) {
534 in->unget = 0;
535 return in->buffer;
536 }
537
538 /* skip whitespace and comments */
539
540 while((car = getc(fp)) != EOF) {
541 if(car == '/') {
542 car1 = getc(fp);
543 if(car1 == '*') skipComment(in);
544 else if(car1 == '/') skipEOL(in);
545 else {
546 car1 = ungetc(car1,fp);
547 break;
548 }
549 }
550 else if(car == '\n') in->lineno++;
551 else if(!isspace(car)) break;
552 }
553
554 switch(car) {
555 case EOF:
556 in->type = ENDFILE;
557 break;
558 case ',':
559 in->type = COMA;
560 in->buffer[pos] = car;
561 pos++;
562 break;
563 case '(':
564 in->type = LPARENTHESIS;
565 in->buffer[pos] = car;
566 pos++;
567 break;
568 case ')':
569 in->type = RPARENTHESIS;
570 in->buffer[pos] = car;
571 pos++;
572 break;
573 case ';':
574 in->type = SEMICOLON;
575 in->buffer[pos] = car;
576 pos++;
577 break;
578 case '=':
579 in->type = EQUAL;
580 in->buffer[pos] = car;
581 pos++;
582 break;
583 case '"':
584 escaped = 0;
585 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
586 if(car == '\\' && escaped == 0) {
587 in->buffer[pos] = car;
588 pos++;
589 escaped = 1;
590 continue;
591 }
592 if(car == '"' && escaped == 0) break;
593 if(car == '\n' && escaped == 0) {
594 in->error(in, "non escaped newline inside quoted string");
595 }
596 if(car == '\n') in->lineno++;
597 in->buffer[pos] = car;
598 pos++;
599 escaped = 0;
600 }
601 if(car == EOF) in->error(in,"no ending quotemark");
602 if(pos == BUFFER_SIZE) in->error(in, "quoted string token too large");
603 in->type = QUOTEDSTRING;
604 break;
605 default:
606 if(isdigit(car)) {
607 in->buffer[pos] = car;
608 pos++;
609 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
610 if(!isdigit(car)) {
611 ungetc(car,fp);
612 break;
613 }
614 in->buffer[pos] = car;
615 pos++;
616 }
617 if(car == EOF) ungetc(car,fp);
618 if(pos == BUFFER_SIZE) in->error(in, "number token too large");
619 in->type = NUMBER;
620 }
621 else if(isalpha(car)) {
622 in->buffer[0] = car;
623 pos = 1;
624 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
625 if(!isalnum(car)) {
626 ungetc(car,fp);
627 break;
628 }
629 in->buffer[pos] = car;
630 pos++;
631 }
632 if(car == EOF) ungetc(car,fp);
633 if(pos == BUFFER_SIZE) in->error(in, "name token too large");
634 in->type = NAME;
635 }
636 else in->error(in, "invalid character, unrecognized token");
637 }
638 in->buffer[pos] = 0;
639 return in->buffer;
640 }
641
642 void skipComment(parse_file * in)
643 {
644 char car;
645 while((car = getc(in->fp)) != EOF) {
646 if(car == '\n') in->lineno++;
647 else if(car == '*') {
648 car = getc(in->fp);
649 if(car ==EOF) break;
650 if(car == '/') return;
651 ungetc(car,in->fp);
652 }
653 }
654 if(car == EOF) in->error(in,"comment begining with '/*' has no ending '*/'");
655 }
656
657 void skipEOL(parse_file * in)
658 {
659 char car;
660 while((car = getc(in->fp)) != EOF) {
661 if(car == '\n') {
662 ungetc(car,in->fp);
663 break;
664 }
665 }
666 if(car == EOF)ungetc(car, in->fp);
667 }
668
669 int isalpha(char c)
670 {
671 int i,j;
672 if(c == '_')return 1;
673 i = c - 'a';
674 j = c - 'A';
675 if((i>=0 && i<26) || (j>=0 && j<26)) return 1;
676 return 0;
677 }
678
679 int isalnum(char c)
680 {
681 return (isalpha(c) || isdigit(c));
682 }
683
684 /*****************************************************************************
685 *Function name
686 * checkNamedTypesImplemented : check if all named types have definition
687 ****************************************************************************/
688
689 void checkNamedTypesImplemented(table * named_types)
690 {
691 type_descriptor *t;
692 int pos;
693 char str[256];
694
695 for(pos = 0 ; pos < named_types->values.position; pos++) {
696 t = (type_descriptor *) named_types->values.array[pos];
697 if(t->type == NONE){
698 sprintf(str,"named type '%s' has no definition",(char*)named_types->keys.array[pos]);
699 error_callback(NULL,str);
700 }
701 }
702 }
703
704
705 /*****************************************************************************
706 *Function name
707 * generateChecksum : generate checksum for the facility
708 *Input Params
709 * facName : name of facility
710 *Output Params
711 * checksum : checksum for the facility
712 ****************************************************************************/
713
714 void generateChecksum( char* facName, unsigned long * checksum, sequence * events)
715 {
716 unsigned long crc ;
717 int pos, nestedStruct;
718 event * ev;
719 char str[256];
720
721 crc = crc32(facName);
722 for(pos = 0; pos < events->position; pos++){
723 ev = (event *)(events->array[pos]);
724 ev->nested = 0; //by default, event has no nested struct
725 crc = partial_crc32(ev->name,crc);
726 nestedStruct = 0;
727 if(ev->type->type != STRUCT){
728 sprintf(str,"event '%s' has a type other than STRUCT",ev->name);
729 error_callback(NULL, str);
730 }
731 crc = getTypeChecksum(crc, ev->type,&nestedStruct);
732 if(nestedStruct ) ev->nested = 1;
733 }
734 *checksum = crc;
735 }
736
737 /*****************************************************************************
738 *Function name
739 * getTypeChecksum : generate checksum by type info
740 *Input Params
741 * crc : checksum generated so far
742 * type : type descriptor containing type info
743 *Return value
744 * unsigned long : checksum
745 *****************************************************************************/
746
747 unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor * type,
748 int * nestedStruct)
749 {
750 unsigned long crc = aCrc;
751 char * str = NULL, buf[16];
752 int flag = 0, pos, max, min;
753 field * fld;
754 data_type dt;
755
756 switch(type->type){
757 case INT:
758 str = intOutputTypes[type->size];
759 break;
760 case UINT:
761 str = uintOutputTypes[type->size];
762 break;
763 case FLOAT:
764 str = floatOutputTypes[type->size];
765 break;
766 case STRING:
767 str = allocAndCopy("string");
768 flag = 1;
769 break;
770 case ENUM:
771 str = appendString("enum ", uintOutputTypes[type->size]);
772 flag = 1;
773 break;
774 case ARRAY:
775 sprintf(buf,"%d\0",type->size);
776 str = appendString("array ",buf);
777 flag = 1;
778 break;
779 case SEQUENCE:
780 sprintf(buf,"%d\0",type->size);
781 str = appendString("sequence ",buf);
782 flag = 1;
783 break;
784 case STRUCT:
785 str = allocAndCopy("struct");
786 flag = 1;
787 break;
788 default:
789 error_callback(NULL, "named type has no definition");
790 break;
791 }
792
793 crc = partial_crc32(str,crc);
794 if(flag) free(str);
795
796 if(type->fmt) crc = partial_crc32(type->fmt,crc);
797
798 if(type->type == ARRAY || type->type == SEQUENCE){
799 dt = type->nested_type->type;
800 if(dt == ARRAY || dt == SEQUENCE || dt == STRUCT) *nestedStruct += 1;
801 crc = getTypeChecksum(crc,type->nested_type,nestedStruct);
802 }else if(type->type == STRUCT){
803 if(type->fields.position != 0){//not a empty struct
804 max = 0;
805 for(pos =0; pos < type->fields.position; pos++){
806 min = 0;
807 fld = (field *) type->fields.array[pos];
808 crc = partial_crc32(fld->name,crc);
809 if(fld->type->type == STRUCT) min++;
810 crc = getTypeChecksum(crc, fld->type,&min);
811 if(min>max) max = min;
812 }
813 *nestedStruct += max;
814 }
815 }else if(type->type == ENUM){
816 for(pos = 0; pos < type->labels.position; pos++)
817 crc = partial_crc32((char*)type->labels.array[pos],crc);
818 }
819
820 return crc;
821 }
822
823
824 /* Event type descriptors */
825 void freeType(type_descriptor * tp)
826 {
827 int pos2;
828 field *f;
829
830 if(tp->fmt != NULL) free(tp->fmt);
831 if(tp->type == ENUM) {
832 for(pos2 = 0; pos2 < tp->labels.position; pos2++) {
833 free(tp->labels.array[pos2]);
834 }
835 sequence_dispose(&(tp->labels));
836 }
837 if(tp->type == STRUCT) {
838 for(pos2 = 0; pos2 < tp->fields.position; pos2++) {
839 f = (field *) tp->fields.array[pos2];
840 free(f->name);
841 free(f->description);
842 free(f);
843 }
844 sequence_dispose(&(tp->fields));
845 }
846 }
847
848 void freeNamedType(table * t)
849 {
850 int pos;
851 type_descriptor * td;
852
853 for(pos = 0 ; pos < t->keys.position; pos++) {
854 free((char *)t->keys.array[pos]);
855 td = (type_descriptor*)t->values.array[pos];
856 freeType(td);
857 free(td);
858 }
859 }
860
861 void freeTypes(sequence *t)
862 {
863 int pos, pos2;
864 type_descriptor *tp;
865 field *f;
866
867 for(pos = 0 ; pos < t->position; pos++) {
868 tp = (type_descriptor *)t->array[pos];
869 freeType(tp);
870 free(tp);
871 }
872 }
873
874 void freeEvents(sequence *t)
875 {
876 int pos;
877 event *ev;
878
879 for(pos = 0 ; pos < t->position; pos++) {
880 ev = (event *) t->array[pos];
881 free(ev->name);
882 free(ev->description);
883 free(ev);
884 }
885
886 }
887
888
889 /* Extensible array */
890
891 void sequence_init(sequence *t)
892 {
893 t->size = 10;
894 t->position = 0;
895 t->array = (void **)memAlloc(t->size * sizeof(void *));
896 }
897
898 void sequence_dispose(sequence *t)
899 {
900 t->size = 0;
901 free(t->array);
902 t->array = NULL;
903 }
904
905 void sequence_push(sequence *t, void *elem)
906 {
907 void **tmp;
908
909 if(t->position >= t->size) {
910 tmp = t->array;
911 t->array = (void **)memAlloc(t->size * 2 * sizeof(void *));
912 memcpy(t->array, tmp, t->size * sizeof(void *));
913 t->size = t->size * 2;
914 free(tmp);
915 }
916 t->array[t->position] = elem;
917 t->position++;
918 }
919
920 void *sequence_pop(sequence *t)
921 {
922 return t->array[t->position--];
923 }
924
925
926 /* Hash table API, implementation is just linear search for now */
927
928 void table_init(table *t)
929 {
930 sequence_init(&(t->keys));
931 sequence_init(&(t->values));
932 }
933
934 void table_dispose(table *t)
935 {
936 sequence_dispose(&(t->keys));
937 sequence_dispose(&(t->values));
938 }
939
940 void table_insert(table *t, char *key, void *value)
941 {
942 sequence_push(&(t->keys),key);
943 sequence_push(&(t->values),value);
944 }
945
946 void *table_find(table *t, char *key)
947 {
948 int pos;
949 for(pos = 0 ; pos < t->keys.position; pos++) {
950 if(strcmp((char *)key,(char *)t->keys.array[pos]) == 0)
951 return(t->values.array[pos]);
952 }
953 return NULL;
954 }
955
956 void table_insert_int(table *t, int *key, void *value)
957 {
958 sequence_push(&(t->keys),key);
959 sequence_push(&(t->values),value);
960 }
961
962 void *table_find_int(table *t, int *key)
963 {
964 int pos;
965 for(pos = 0 ; pos < t->keys.position; pos++) {
966 if(*key == *(int *)t->keys.array[pos])
967 return(t->values.array[pos]);
968 }
969 return NULL;
970 }
971
972
973 /* Concatenate strings */
974
975 char *appendString(char *s, char *suffix)
976 {
977 char *tmp;
978
979 tmp = (char *)memAlloc(strlen(s) + strlen(suffix) + 1);
980 strcpy(tmp,s);
981 strcat(tmp,suffix);
982 return tmp;
983 }
984
985
This page took 0.084937 seconds and 4 git commands to generate.