3 parser.c: Generate helper declarations and functions to trace events
4 from an event description file.
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.
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.
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
22 /* This program reads the ".xml" event definitions input files
23 and constructs structure for each event.
25 The program uses a very simple tokenizer, called from a hand written
26 recursive descent parser to fill a data structure describing the events.
27 The result is a sequence of events definitions which refer to type
30 A table of named types is maintained to allow refering to types by name
31 when the same type is used at several places. Finally a sequence of
32 all types is maintained to facilitate the freeing of all type
33 information when the processing of an ".xml" file is finished. */
40 #include <linux/errno.h>
47 static int ltt_isalpha(char c
)
53 if((i
>=0 && i
<26) || (j
>=0 && j
<26)) return 1;
57 static int ltt_isalnum(char c
)
59 return (ltt_isalpha(c
) || isdigit(c
));
62 /*****************************************************************************
64 * getSize : translate from string to integer
66 * in : input file handle
69 *****************************************************************************/
71 int getSize(parse_file
*in
)
76 if(in
->type
== NUMBER
) {
77 if(strcmp(token
,"1") == 0) return 0;
78 else if(strcmp(token
,"2") == 0) return 1;
79 else if(strcmp(token
,"4") == 0) return 2;
80 else if(strcmp(token
,"8") == 0) return 3;
82 else if(in
->type
== NAME
) {
83 if(strcmp(token
,"short") == 0) return 4;
84 else if(strcmp(token
,"medium") == 0) return 5;
85 else if(strcmp(token
,"long") == 0) return 6;
87 in
->error(in
,"incorrect size specification");
91 /*****************************************************************************
93 * error_callback : print out error info
95 * in : input file handle
96 * msg : message to be printed
97 ****************************************************************************/
99 void error_callback(parse_file
*in
, char *msg
)
102 printf("Error in file %s, line %d: %s\n", in
->name
, in
->lineno
, msg
);
107 /*****************************************************************************
109 * memAlloc : allocate memory
111 * size : required memory size
113 * void * : pointer to allocate memory or NULL
114 ****************************************************************************/
116 void * memAlloc(int size
)
119 if(size
== 0) return NULL
;
122 printf("Failed to allocate memory");
128 /*****************************************************************************
130 * allocAndCopy : allocate memory and initialize it
132 * str : string to be put in memory
134 * char * : pointer to allocate memory or NULL
135 ****************************************************************************/
137 char *allocAndCopy(char *str
)
140 if(str
== NULL
) return NULL
;
141 addr
= (char *)memAlloc(strlen(str
)+1);
146 /**************************************************************************
148 * getNameAttribute,getFormatAttribute,getSizeAttribute,getValueAttribute
149 * getValueStrAttribute
151 * Read the attribute from the input file.
154 * in , input file handle.
157 * address of the attribute.
159 **************************************************************************/
161 char * getNameAttribute(parse_file
*in
)
165 if(strcmp("name",token
))in
->error(in
,"name was expected");
168 car
= seekNextChar(in
);
169 if(car
== EOF
)in
->error(in
,"name was expected");
170 else if(car
== '\"')token
= getQuotedString(in
);
171 else token
= getName(in
);
175 char * getFormatAttribute(parse_file
*in
)
179 //format is an option
180 token
= getToken(in
);
181 if(strcmp("/",token
) == 0 || strcmp(">",token
) == 0){
186 if(strcmp("format",token
))in
->error(in
,"format was expected");
188 token
= getQuotedString(in
);
192 int getSizeAttribute(parse_file
*in
)
194 /* skip name and equal */
201 int getValueAttribute(parse_file
*in
)
203 /* skip name and equal */
207 return getNumber(in
);
210 //for <label name=label_name value=n/>, value is an option
211 char * getValueStrAttribute(parse_file
*in
)
215 token
= getToken(in
);
216 if(strcmp("/",token
) == 0){
221 if(strcmp("value",token
))in
->error(in
,"value was expected");
223 token
= getToken(in
);
224 if(in
->type
!= NUMBER
) in
->error(in
,"number was expected");
228 char * getDescription(parse_file
*in
)
231 char * token
, car
, *str
;
235 getLAnglebracket(in
);
237 if(strcmp("description",token
)){
238 fseek(in
->fp
, pos
, SEEK_SET
);
242 getRAnglebracket(in
);
245 while((car
= getc(in
->fp
)) != EOF
) {
246 if(car
== '<') break;
247 if(car
== '\0') continue;
248 in
->buffer
[pos
] = car
;
251 if(car
== EOF
)in
->error(in
,"not a valid description");
252 in
->buffer
[pos
] = '\0';
254 str
= allocAndCopy(in
->buffer
);
258 if(strcmp("description", token
))in
->error(in
,"not a valid description");
259 getRAnglebracket(in
);
264 /*****************************************************************************
266 * parseFacility : generate event list
268 * in : input file handle
269 * fac : empty facility
271 * fac : facility filled with event list
272 ****************************************************************************/
274 void parseFacility(parse_file
*in
, facility_t
* fac
)
279 fac
->name
= allocAndCopy(getNameAttribute(in
));
280 getRAnglebracket(in
);
282 fac
->description
= getDescription(in
);
285 getLAnglebracket(in
);
287 token
= getToken(in
);
288 if(in
->type
== ENDFILE
)
289 in
->error(in
,"the definition of the facility is not finished");
291 if(strcmp("event",token
) == 0){
292 ev
= (event_t
*) memAlloc(sizeof(event_t
));
293 sequence_push(&(fac
->events
),ev
);
294 parseEvent(in
,ev
, &(fac
->unnamed_types
), &(fac
->named_types
));
295 }else if(strcmp("type",token
) == 0){
296 parseTypeDefinition(in
, &(fac
->unnamed_types
), &(fac
->named_types
));
297 }else if(in
->type
== FORWARDSLASH
){
299 }else in
->error(in
,"event or type token expected\n");
303 if(strcmp("facility",token
)) in
->error(in
,"not the end of the facility");
304 getRAnglebracket(in
); //</facility>
307 /*****************************************************************************
309 * parseEvent : generate event from event definition
311 * in : input file handle
313 * unnamed_types : array of unamed types
314 * named_types : array of named types
316 * ev : new event (parameters are passed to it)
317 ****************************************************************************/
319 void parseEvent(parse_file
*in
, event_t
* ev
, sequence
* unnamed_types
,
324 //<event name=eventtype_name>
325 ev
->name
= allocAndCopy(getNameAttribute(in
));
326 getRAnglebracket(in
);
328 //<description>...</descriptio>
329 ev
->description
= getDescription(in
);
331 //event can have STRUCT, TYPEREF or NOTHING
332 getLAnglebracket(in
);
334 token
= getToken(in
);
335 if(in
->type
== FORWARDSLASH
){ //</event> NOTHING
337 }else if(in
->type
== NAME
){
338 if(strcmp("struct",token
)==0 || strcmp("typeref",token
)==0){
340 ev
->type
= parseType(in
,NULL
, unnamed_types
, named_types
);
341 if(ev
->type
->type
!= STRUCT
&& ev
->type
->type
!= NONE
)
342 in
->error(in
,"type must be a struct");
343 }else in
->error(in
, "not a valid type");
345 getLAnglebracket(in
);
347 }else in
->error(in
,"not a struct type");
350 if(strcmp("event",token
))in
->error(in
,"not an event definition");
351 getRAnglebracket(in
); //</event>
354 /*****************************************************************************
356 * parseField : get field infomation from buffer
358 * in : input file handle
359 * t : type descriptor
360 * unnamed_types : array of unamed types
361 * named_types : array of named types
362 ****************************************************************************/
364 void parseFields(parse_file
*in
, type_descriptor
*t
, sequence
* unnamed_types
,
370 f
= (type_fields
*)memAlloc(sizeof(type_fields
));
371 sequence_push(&(t
->fields
),f
);
373 //<field name=field_name> <description> <type> </field>
374 f
->name
= allocAndCopy(getNameAttribute(in
));
375 getRAnglebracket(in
);
377 f
->description
= getDescription(in
);
380 getLAnglebracket(in
);
381 f
->type
= parseType(in
,NULL
, unnamed_types
, named_types
);
383 getLAnglebracket(in
);
386 if(strcmp("field",token
))in
->error(in
,"not a valid field definition");
387 getRAnglebracket(in
); //</field>
391 /*****************************************************************************
393 * parseType : get type information, type can be :
395 * int(size,fmt); uint(size,fmt); float(size,fmt);
396 * string(fmt); enum(size,fmt,(label1,label2...))
398 * array(arraySize, type); sequence(lengthSize,type)
399 * struct(field(name,type,description)...)
403 * in : input file handle
404 * inType : a type descriptor
405 * unnamed_types : array of unamed types
406 * named_types : array of named types
408 * type_descriptor* : a type descriptor
409 ****************************************************************************/
411 type_descriptor
*parseType(parse_file
*in
, type_descriptor
*inType
,
412 sequence
* unnamed_types
, table
* named_types
)
418 t
= (type_descriptor
*) memAlloc(sizeof(type_descriptor
));
422 sequence_push(unnamed_types
,t
);
428 if(strcmp(token
,"struct") == 0) {
430 getRAnglebracket(in
); //<struct>
431 getLAnglebracket(in
); //<field name=..>
432 token
= getToken(in
);
433 sequence_init(&(t
->fields
));
434 while(strcmp("field",token
) == 0){
435 parseFields(in
,t
, unnamed_types
, named_types
);
438 getLAnglebracket(in
);
439 token
= getToken(in
);
441 if(strcmp("/",token
))in
->error(in
,"not a valid structure definition");
443 if(strcmp("struct",token
)!=0)
444 in
->error(in
,"not a valid structure definition");
445 getRAnglebracket(in
); //</struct>
447 else if(strcmp(token
,"union") == 0) {
449 t
->size
= getSizeAttribute(in
);
450 getRAnglebracket(in
); //<union typecodesize=isize>
452 getLAnglebracket(in
); //<field name=..>
453 token
= getToken(in
);
454 sequence_init(&(t
->fields
));
455 while(strcmp("field",token
) == 0){
456 parseFields(in
,t
, unnamed_types
, named_types
);
459 getLAnglebracket(in
);
460 token
= getToken(in
);
462 if(strcmp("/",token
))in
->error(in
,"not a valid union definition");
464 if(strcmp("union",token
)!=0)
465 in
->error(in
,"not a valid union definition");
466 getRAnglebracket(in
); //</union>
468 else if(strcmp(token
,"array") == 0) {
470 t
->size
= getValueAttribute(in
);
471 getRAnglebracket(in
); //<array size=n>
473 getLAnglebracket(in
); //<type struct>
474 t
->nested_type
= parseType(in
,NULL
, unnamed_types
, named_types
);
476 getLAnglebracket(in
); //</array>
479 if(strcmp("array",token
))in
->error(in
,"not a valid array definition");
480 getRAnglebracket(in
); //</array>
482 else if(strcmp(token
,"sequence") == 0) {
484 t
->size
= getSizeAttribute(in
);
485 getRAnglebracket(in
); //<array lengthsize=isize>
487 getLAnglebracket(in
); //<type struct>
488 t
->nested_type
= parseType(in
,NULL
, unnamed_types
, named_types
);
490 getLAnglebracket(in
); //</sequence>
493 if(strcmp("sequence",token
))in
->error(in
,"not a valid sequence definition");
494 getRAnglebracket(in
); //</sequence>
496 else if(strcmp(token
,"enum") == 0) {
499 sequence_init(&(t
->labels
));
500 t
->size
= getSizeAttribute(in
);
501 t
->fmt
= allocAndCopy(getFormatAttribute(in
));
502 getRAnglebracket(in
);
504 //<label name=label1 value=n/>
505 getLAnglebracket(in
);
506 token
= getToken(in
); //"label" or "/"
507 while(strcmp("label",token
) == 0){
508 str
= allocAndCopy(getNameAttribute(in
));
509 token
= getValueStrAttribute(in
);
511 str1
= appendString(str
,"=");
513 str
= appendString(str1
,token
);
515 sequence_push(&(t
->labels
),str
);
517 sequence_push(&(t
->labels
),str
);
520 getRAnglebracket(in
);
522 //next label definition
523 getLAnglebracket(in
);
524 token
= getToken(in
); //"label" or "/"
526 if(strcmp("/",token
))in
->error(in
, "not a valid enum definition");
528 if(strcmp("enum",token
))in
->error(in
, "not a valid enum definition");
529 getRAnglebracket(in
); //</label>
531 else if(strcmp(token
,"int") == 0) {
533 t
->size
= getSizeAttribute(in
);
534 t
->fmt
= allocAndCopy(getFormatAttribute(in
));
536 getRAnglebracket(in
);
538 else if(strcmp(token
,"uint") == 0) {
540 t
->size
= getSizeAttribute(in
);
541 t
->fmt
= allocAndCopy(getFormatAttribute(in
));
543 getRAnglebracket(in
);
545 else if(strcmp(token
,"float") == 0) {
547 t
->size
= getSizeAttribute(in
);
548 t
->fmt
= allocAndCopy(getFormatAttribute(in
));
550 getRAnglebracket(in
);
552 else if(strcmp(token
,"string") == 0) {
554 t
->fmt
= allocAndCopy(getFormatAttribute(in
));
556 getRAnglebracket(in
);
558 else if(strcmp(token
,"typeref") == 0){
559 // Must be a named type
561 in
->error(in
,"Named type cannot refer to a named type");
564 sequence_pop(unnamed_types
);
565 token
= getNameAttribute(in
);
566 t
= find_named_type(token
, named_types
);
567 getForwardslash(in
); //<typeref name=type_name/>
568 getRAnglebracket(in
);
571 }else in
->error(in
,"not a valid type");
576 /*****************************************************************************
578 * find_named_type : find a named type from hash table
581 * named_types : array of named types
583 * type_descriptor * : a type descriptor
584 *****************************************************************************/
586 type_descriptor
* find_named_type(char *name
, table
* named_types
)
590 t
= table_find(named_types
,name
);
592 t
= (type_descriptor
*)memAlloc(sizeof(type_descriptor
));
593 t
->type_name
= allocAndCopy(name
);
596 table_insert(named_types
,t
->type_name
,t
);
597 // table_insert(named_types,allocAndCopy(name),t);
602 /*****************************************************************************
604 * parseTypeDefinition : get type information from type definition
606 * in : input file handle
607 * unnamed_types : array of unamed types
608 * named_types : array of named types
609 *****************************************************************************/
611 void parseTypeDefinition(parse_file
* in
, sequence
* unnamed_types
,
617 token
= getNameAttribute(in
);
618 t
= find_named_type(token
, named_types
);
620 if(t
->type
!= NONE
) in
->error(in
,"redefinition of named type");
621 getRAnglebracket(in
); //<type name=type_name>
622 getLAnglebracket(in
); //<struct>
624 if(strcmp("struct",token
))in
->error(in
,"not a valid type definition");
626 parseType(in
,t
, unnamed_types
, named_types
);
629 getLAnglebracket(in
);
632 if(strcmp("type",token
))in
->error(in
,"not a valid type definition");
633 getRAnglebracket(in
); //</type>
636 /**************************************************************************
638 * getComa, getName, getNumber, getEqual
640 * Read a token from the input file, check its type, return it scontent.
643 * in , input file handle.
646 * address of token content.
648 **************************************************************************/
650 char *getName(parse_file
* in
)
654 token
= getToken(in
);
655 if(in
->type
!= NAME
) in
->error(in
,"Name token was expected");
659 int getNumber(parse_file
* in
)
663 token
= getToken(in
);
664 if(in
->type
!= NUMBER
) in
->error(in
, "Number token was expected");
668 char *getForwardslash(parse_file
* in
)
672 token
= getToken(in
);
673 if(in
->type
!= FORWARDSLASH
) in
->error(in
, "forward slash token was expected");
677 char *getLAnglebracket(parse_file
* in
)
681 token
= getToken(in
);
682 if(in
->type
!= LANGLEBRACKET
) in
->error(in
, "Left angle bracket was expected");
686 char *getRAnglebracket(parse_file
* in
)
690 token
= getToken(in
);
691 if(in
->type
!= RANGLEBRACKET
) in
->error(in
, "Right angle bracket was expected");
695 char *getQuotedString(parse_file
* in
)
699 token
= getToken(in
);
700 if(in
->type
!= QUOTEDSTRING
) in
->error(in
, "quoted string was expected");
704 char * getEqual(parse_file
*in
)
708 token
= getToken(in
);
709 if(in
->type
!= EQUAL
) in
->error(in
, "equal was expected");
713 char seekNextChar(parse_file
*in
)
716 while((car
= getc(in
->fp
)) != EOF
) {
725 /******************************************************************
727 * getToken, ungetToken
729 * Read a token from the input file and return its type and content.
730 * Line numbers are accounted for and whitespace/comments are skipped.
733 * in, input file handle.
736 * address of token content.
738 ******************************************************************/
740 void ungetToken(parse_file
* in
)
745 char *getToken(parse_file
* in
)
749 int pos
= 0, escaped
;
756 /* skip whitespace and comments */
758 while((car
= getc(fp
)) != EOF
) {
761 if(car1
== '*') skipComment(in
);
762 else if(car1
== '/') skipEOL(in
);
764 car1
= ungetc(car1
,fp
);
768 else if(car
== '\n') in
->lineno
++;
769 else if(!isspace(car
)) break;
777 in
->type
= FORWARDSLASH
;
778 in
->buffer
[pos
] = car
;
782 in
->type
= LANGLEBRACKET
;
783 in
->buffer
[pos
] = car
;
787 in
->type
= RANGLEBRACKET
;
788 in
->buffer
[pos
] = car
;
793 in
->buffer
[pos
] = car
;
798 while((car
= getc(fp
)) != EOF
&& pos
< BUFFER_SIZE
) {
799 if(car
== '\\' && escaped
== 0) {
800 in
->buffer
[pos
] = car
;
805 if(car
== '"' && escaped
== 0) break;
806 if(car
== '\n' && escaped
== 0) {
807 in
->error(in
, "non escaped newline inside quoted string");
809 if(car
== '\n') in
->lineno
++;
810 in
->buffer
[pos
] = car
;
814 if(car
== EOF
) in
->error(in
,"no ending quotemark");
815 if(pos
== BUFFER_SIZE
) in
->error(in
, "quoted string token too large");
816 in
->type
= QUOTEDSTRING
;
820 in
->buffer
[pos
] = car
;
822 while((car
= getc(fp
)) != EOF
&& pos
< BUFFER_SIZE
) {
827 in
->buffer
[pos
] = car
;
830 if(car
== EOF
) ungetc(car
,fp
);
831 if(pos
== BUFFER_SIZE
) in
->error(in
, "number token too large");
834 else if(ltt_isalpha(car
)) {
837 while((car
= getc(fp
)) != EOF
&& pos
< BUFFER_SIZE
) {
838 if(!ltt_isalnum(car
)) {
842 in
->buffer
[pos
] = car
;
845 if(car
== EOF
) ungetc(car
,fp
);
846 if(pos
== BUFFER_SIZE
) in
->error(in
, "name token too large");
849 else in
->error(in
, "invalid character, unrecognized token");
855 void skipComment(parse_file
* in
)
858 while((car
= getc(in
->fp
)) != EOF
) {
859 if(car
== '\n') in
->lineno
++;
860 else if(car
== '*') {
863 if(car
== '/') return;
867 if(car
== EOF
) in
->error(in
,"comment begining with '/*' has no ending '*/'");
870 void skipEOL(parse_file
* in
)
873 while((car
= getc(in
->fp
)) != EOF
) {
879 if(car
== EOF
)ungetc(car
, in
->fp
);
882 /*****************************************************************************
884 * checkNamedTypesImplemented : check if all named types have definition
885 * returns -1 on error, 0 if ok
886 ****************************************************************************/
888 int checkNamedTypesImplemented(table
* named_types
)
894 for(pos
= 0 ; pos
< named_types
->values
.position
; pos
++) {
895 t
= (type_descriptor
*) named_types
->values
.array
[pos
];
897 sprintf(str
,"named type '%s' has no definition",
898 (char*)named_types
->keys
.array
[pos
]);
899 error_callback(NULL
,str
);
907 /*****************************************************************************
909 * generateChecksum : generate checksum for the facility
911 * facName : name of facility
913 * checksum : checksum for the facility
914 ****************************************************************************/
916 int generateChecksum(char* facName
, guint32
* checksum
, sequence
* events
)
923 crc
= crc32(facName
);
924 for(pos
= 0; pos
< events
->position
; pos
++){
925 ev
= (event_t
*)(events
->array
[pos
]);
926 crc
= partial_crc32(ev
->name
,crc
);
927 if(!ev
->type
) continue; //event without type
928 if(ev
->type
->type
!= STRUCT
){
929 sprintf(str
,"event '%s' has a type other than STRUCT",ev
->name
);
930 error_callback(NULL
, str
);
933 crc
= getTypeChecksum(crc
, ev
->type
);
939 /*****************************************************************************
941 * getTypeChecksum : generate checksum by type info
943 * crc : checksum generated so far
944 * type : type descriptor containing type info
946 * unsigned long : checksum
947 *****************************************************************************/
949 unsigned long getTypeChecksum(unsigned long aCrc
, type_descriptor
* type
)
951 unsigned long crc
= aCrc
;
952 char * str
= NULL
, buf
[16];
958 str
= intOutputTypes
[type
->size
];
961 str
= uintOutputTypes
[type
->size
];
964 str
= floatOutputTypes
[type
->size
];
967 str
= allocAndCopy("string");
971 str
= appendString("enum ", uintOutputTypes
[type
->size
]);
975 sprintf(buf
,"%d",type
->size
);
976 str
= appendString("array ",buf
);
980 sprintf(buf
,"%d",type
->size
);
981 str
= appendString("sequence ",buf
);
985 str
= allocAndCopy("struct");
989 str
= allocAndCopy("union");
993 error_callback(NULL
, "named type has no definition");
997 crc
= partial_crc32(str
,crc
);
1000 if(type
->fmt
) crc
= partial_crc32(type
->fmt
,crc
);
1002 if(type
->type
== ARRAY
|| type
->type
== SEQUENCE
){
1003 crc
= getTypeChecksum(crc
,type
->nested_type
);
1004 }else if(type
->type
== STRUCT
|| type
->type
== UNION
){
1005 for(pos
=0; pos
< type
->fields
.position
; pos
++){
1006 fld
= (type_fields
*) type
->fields
.array
[pos
];
1007 crc
= partial_crc32(fld
->name
,crc
);
1008 crc
= getTypeChecksum(crc
, fld
->type
);
1010 }else if(type
->type
== ENUM
){
1011 for(pos
= 0; pos
< type
->labels
.position
; pos
++)
1012 crc
= partial_crc32((char*)type
->labels
.array
[pos
],crc
);
1019 /* Event type descriptors */
1020 void freeType(type_descriptor
* tp
)
1025 if(tp
->fmt
!= NULL
) free(tp
->fmt
);
1026 if(tp
->type
== ENUM
) {
1027 for(pos2
= 0; pos2
< tp
->labels
.position
; pos2
++) {
1028 free(tp
->labels
.array
[pos2
]);
1030 sequence_dispose(&(tp
->labels
));
1032 if(tp
->type
== STRUCT
) {
1033 for(pos2
= 0; pos2
< tp
->fields
.position
; pos2
++) {
1034 f
= (type_fields
*) tp
->fields
.array
[pos2
];
1036 free(f
->description
);
1039 sequence_dispose(&(tp
->fields
));
1043 void freeNamedType(table
* t
)
1046 type_descriptor
* td
;
1048 for(pos
= 0 ; pos
< t
->keys
.position
; pos
++) {
1049 free((char *)t
->keys
.array
[pos
]);
1050 td
= (type_descriptor
*)t
->values
.array
[pos
];
1056 void freeTypes(sequence
*t
)
1059 type_descriptor
*tp
;
1061 for(pos
= 0 ; pos
< t
->position
; pos
++) {
1062 tp
= (type_descriptor
*)t
->array
[pos
];
1068 void freeEvents(sequence
*t
)
1073 for(pos
= 0 ; pos
< t
->position
; pos
++) {
1074 ev
= (event_t
*) t
->array
[pos
];
1076 free(ev
->description
);
1083 /* Extensible array */
1085 void sequence_init(sequence
*t
)
1089 t
->array
= (void **)memAlloc(t
->size
* sizeof(void *));
1092 void sequence_dispose(sequence
*t
)
1099 void sequence_push(sequence
*t
, void *elem
)
1103 if(t
->position
>= t
->size
) {
1105 t
->array
= (void **)memAlloc(t
->size
* 2 * sizeof(void *));
1106 memcpy(t
->array
, tmp
, t
->size
* sizeof(void *));
1107 t
->size
= t
->size
* 2;
1110 t
->array
[t
->position
] = elem
;
1114 void *sequence_pop(sequence
*t
)
1116 return t
->array
[t
->position
--];
1120 /* Hash table API, implementation is just linear search for now */
1122 void table_init(table
*t
)
1124 sequence_init(&(t
->keys
));
1125 sequence_init(&(t
->values
));
1128 void table_dispose(table
*t
)
1130 sequence_dispose(&(t
->keys
));
1131 sequence_dispose(&(t
->values
));
1134 void table_insert(table
*t
, char *key
, void *value
)
1136 sequence_push(&(t
->keys
),key
);
1137 sequence_push(&(t
->values
),value
);
1140 void *table_find(table
*t
, char *key
)
1143 for(pos
= 0 ; pos
< t
->keys
.position
; pos
++) {
1144 if(strcmp((char *)key
,(char *)t
->keys
.array
[pos
]) == 0)
1145 return(t
->values
.array
[pos
]);
1150 void table_insert_int(table
*t
, int *key
, void *value
)
1152 sequence_push(&(t
->keys
),key
);
1153 sequence_push(&(t
->values
),value
);
1156 void *table_find_int(table
*t
, int *key
)
1159 for(pos
= 0 ; pos
< t
->keys
.position
; pos
++) {
1160 if(*key
== *(int *)t
->keys
.array
[pos
])
1161 return(t
->values
.array
[pos
]);
1167 /* Concatenate strings */
1169 char *appendString(char *s
, char *suffix
)
1172 if(suffix
== NULL
) return s
;
1174 tmp
= (char *)memAlloc(strlen(s
) + strlen(suffix
) + 1);
This page took 0.078601 seconds and 4 git commands to generate.