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>
46 static int ltt_isalpha(char c
)
52 if((i
>=0 && i
<26) || (j
>=0 && j
<26)) return 1;
56 static int ltt_isalnum(char c
)
58 return (ltt_isalpha(c
) || isdigit(c
));
61 /*****************************************************************************
63 * getSize : translate from string to integer
65 * in : input file handle
68 *****************************************************************************/
70 int getSize(parse_file
*in
)
75 if(in
->type
== NUMBER
) {
76 if(strcmp(token
,"1") == 0) return 0;
77 else if(strcmp(token
,"2") == 0) return 1;
78 else if(strcmp(token
,"4") == 0) return 2;
79 else if(strcmp(token
,"8") == 0) return 3;
81 else if(in
->type
== NAME
) {
82 if(strcmp(token
,"short") == 0) return 4;
83 else if(strcmp(token
,"medium") == 0) return 5;
84 else if(strcmp(token
,"long") == 0) return 6;
86 in
->error(in
,"incorrect size specification");
90 /*****************************************************************************
92 * error_callback : print out error info
94 * in : input file handle
95 * msg : message to be printed
96 ****************************************************************************/
98 void error_callback(parse_file
*in
, char *msg
)
101 printf("Error in file %s, line %d: %s\n", in
->name
, in
->lineno
, msg
);
106 /*****************************************************************************
108 * memAlloc : allocate memory
110 * size : required memory size
112 * void * : pointer to allocate memory or NULL
113 ****************************************************************************/
115 void * memAlloc(int size
)
118 if(size
== 0) return NULL
;
121 printf("Failed to allocate memory");
127 /*****************************************************************************
129 * allocAndCopy : allocate memory and initialize it
131 * str : string to be put in memory
133 * char * : pointer to allocate memory or NULL
134 ****************************************************************************/
136 char *allocAndCopy(char *str
)
139 if(str
== NULL
) return NULL
;
140 addr
= (char *)memAlloc(strlen(str
)+1);
145 /**************************************************************************
147 * getNameAttribute,getFormatAttribute,getSizeAttribute,getValueAttribute
148 * getValueStrAttribute
150 * Read the attribute from the input file.
153 * in , input file handle.
156 * address of the attribute.
158 **************************************************************************/
160 char * getNameAttribute(parse_file
*in
)
164 if(strcmp("name",token
))in
->error(in
,"name was expected");
167 car
= seekNextChar(in
);
168 if(car
== EOF
)in
->error(in
,"name was expected");
169 else if(car
== '\"')token
= getQuotedString(in
);
170 else token
= getName(in
);
174 char * getFormatAttribute(parse_file
*in
)
178 //format is an option
179 token
= getToken(in
);
180 if(strcmp("/",token
) == 0 || strcmp(">",token
) == 0){
185 if(strcmp("format",token
))in
->error(in
,"format was expected");
187 token
= getQuotedString(in
);
191 int getSizeAttribute(parse_file
*in
)
193 /* skip name and equal */
200 int getValueAttribute(parse_file
*in
)
202 /* skip name and equal */
206 return getNumber(in
);
209 //for <label name=label_name value=n/>, value is an option
210 char * getValueStrAttribute(parse_file
*in
)
214 token
= getToken(in
);
215 if(strcmp("/",token
) == 0){
220 if(strcmp("value",token
))in
->error(in
,"value was expected");
222 token
= getToken(in
);
223 if(in
->type
!= NUMBER
) in
->error(in
,"number was expected");
227 char * getDescription(parse_file
*in
)
230 char * token
, car
, *str
;
234 getLAnglebracket(in
);
236 if(strcmp("description",token
)){
237 fseek(in
->fp
, pos
, SEEK_SET
);
241 getRAnglebracket(in
);
244 while((car
= getc(in
->fp
)) != EOF
) {
245 if(car
== '<') break;
246 if(car
== '\0') continue;
247 in
->buffer
[pos
] = car
;
250 if(car
== EOF
)in
->error(in
,"not a valid description");
251 in
->buffer
[pos
] = '\0';
253 str
= allocAndCopy(in
->buffer
);
257 if(strcmp("description", token
))in
->error(in
,"not a valid description");
258 getRAnglebracket(in
);
263 /*****************************************************************************
265 * parseFacility : generate event list
267 * in : input file handle
268 * fac : empty facility
270 * fac : facility filled with event list
271 ****************************************************************************/
273 void parseFacility(parse_file
*in
, facility_t
* fac
)
278 fac
->name
= allocAndCopy(getNameAttribute(in
));
279 getRAnglebracket(in
);
281 fac
->description
= getDescription(in
);
284 getLAnglebracket(in
);
286 token
= getToken(in
);
287 if(in
->type
== ENDFILE
)
288 in
->error(in
,"the definition of the facility is not finished");
290 if(strcmp("event",token
) == 0){
291 ev
= (event_t
*) memAlloc(sizeof(event_t
));
292 sequence_push(&(fac
->events
),ev
);
293 parseEvent(in
,ev
, &(fac
->unnamed_types
), &(fac
->named_types
));
294 }else if(strcmp("type",token
) == 0){
295 parseTypeDefinition(in
, &(fac
->unnamed_types
), &(fac
->named_types
));
296 }else if(in
->type
== FORWARDSLASH
){
298 }else in
->error(in
,"event or type token expected\n");
302 if(strcmp("facility",token
)) in
->error(in
,"not the end of the facility");
303 getRAnglebracket(in
); //</facility>
306 /*****************************************************************************
308 * parseEvent : generate event from event definition
310 * in : input file handle
312 * unnamed_types : array of unamed types
313 * named_types : array of named types
315 * ev : new event (parameters are passed to it)
316 ****************************************************************************/
318 void parseEvent(parse_file
*in
, event_t
* ev
, sequence
* unnamed_types
,
323 //<event name=eventtype_name>
324 ev
->name
= allocAndCopy(getNameAttribute(in
));
325 getRAnglebracket(in
);
327 //<description>...</descriptio>
328 ev
->description
= getDescription(in
);
330 //event can have STRUCT, TYPEREF or NOTHING
331 getLAnglebracket(in
);
333 token
= getToken(in
);
334 if(in
->type
== FORWARDSLASH
){ //</event> NOTHING
336 }else if(in
->type
== NAME
){
337 if(strcmp("struct",token
)==0 || strcmp("typeref",token
)==0){
339 ev
->type
= parseType(in
,NULL
, unnamed_types
, named_types
);
340 if(ev
->type
->type
!= STRUCT
&& ev
->type
->type
!= NONE
)
341 in
->error(in
,"type must be a struct");
342 }else in
->error(in
, "not a valid type");
344 getLAnglebracket(in
);
346 }else in
->error(in
,"not a struct type");
349 if(strcmp("event",token
))in
->error(in
,"not an event definition");
350 getRAnglebracket(in
); //</event>
353 /*****************************************************************************
355 * parseField : get field infomation from buffer
357 * in : input file handle
358 * t : type descriptor
359 * unnamed_types : array of unamed types
360 * named_types : array of named types
361 ****************************************************************************/
363 void parseFields(parse_file
*in
, type_descriptor
*t
, sequence
* unnamed_types
,
369 f
= (type_fields
*)memAlloc(sizeof(type_fields
));
370 sequence_push(&(t
->fields
),f
);
372 //<field name=field_name> <description> <type> </field>
373 f
->name
= allocAndCopy(getNameAttribute(in
));
374 getRAnglebracket(in
);
376 f
->description
= getDescription(in
);
379 getLAnglebracket(in
);
380 f
->type
= parseType(in
,NULL
, unnamed_types
, named_types
);
382 getLAnglebracket(in
);
385 if(strcmp("field",token
))in
->error(in
,"not a valid field definition");
386 getRAnglebracket(in
); //</field>
390 /*****************************************************************************
392 * parseType : get type information, type can be :
394 * int(size,fmt); uint(size,fmt); float(size,fmt);
395 * string(fmt); enum(size,fmt,(label1,label2...))
397 * array(arraySize, type); sequence(lengthSize,type)
398 * struct(field(name,type,description)...)
402 * in : input file handle
403 * inType : a type descriptor
404 * unnamed_types : array of unamed types
405 * named_types : array of named types
407 * type_descriptor* : a type descriptor
408 ****************************************************************************/
410 type_descriptor
*parseType(parse_file
*in
, type_descriptor
*inType
,
411 sequence
* unnamed_types
, table
* named_types
)
417 t
= (type_descriptor
*) memAlloc(sizeof(type_descriptor
));
421 sequence_push(unnamed_types
,t
);
427 if(strcmp(token
,"struct") == 0) {
429 getRAnglebracket(in
); //<struct>
430 getLAnglebracket(in
); //<field name=..>
431 token
= getToken(in
);
432 sequence_init(&(t
->fields
));
433 while(strcmp("field",token
) == 0){
434 parseFields(in
,t
, unnamed_types
, named_types
);
437 getLAnglebracket(in
);
438 token
= getToken(in
);
440 if(strcmp("/",token
))in
->error(in
,"not a valid structure definition");
442 if(strcmp("struct",token
)!=0)
443 in
->error(in
,"not a valid structure definition");
444 getRAnglebracket(in
); //</struct>
446 else if(strcmp(token
,"union") == 0) {
448 t
->size
= getSizeAttribute(in
);
449 getRAnglebracket(in
); //<union typecodesize=isize>
451 getLAnglebracket(in
); //<field name=..>
452 token
= getToken(in
);
453 sequence_init(&(t
->fields
));
454 while(strcmp("field",token
) == 0){
455 parseFields(in
,t
, unnamed_types
, named_types
);
458 getLAnglebracket(in
);
459 token
= getToken(in
);
461 if(strcmp("/",token
))in
->error(in
,"not a valid union definition");
463 if(strcmp("union",token
)!=0)
464 in
->error(in
,"not a valid union definition");
465 getRAnglebracket(in
); //</union>
467 else if(strcmp(token
,"array") == 0) {
469 t
->size
= getValueAttribute(in
);
470 getRAnglebracket(in
); //<array size=n>
472 getLAnglebracket(in
); //<type struct>
473 t
->nested_type
= parseType(in
,NULL
, unnamed_types
, named_types
);
475 getLAnglebracket(in
); //</array>
478 if(strcmp("array",token
))in
->error(in
,"not a valid array definition");
479 getRAnglebracket(in
); //</array>
481 else if(strcmp(token
,"sequence") == 0) {
483 t
->size
= getSizeAttribute(in
);
484 getRAnglebracket(in
); //<array lengthsize=isize>
486 getLAnglebracket(in
); //<type struct>
487 t
->nested_type
= parseType(in
,NULL
, unnamed_types
, named_types
);
489 getLAnglebracket(in
); //</sequence>
492 if(strcmp("sequence",token
))in
->error(in
,"not a valid sequence definition");
493 getRAnglebracket(in
); //</sequence>
495 else if(strcmp(token
,"enum") == 0) {
498 sequence_init(&(t
->labels
));
499 t
->size
= getSizeAttribute(in
);
500 t
->fmt
= allocAndCopy(getFormatAttribute(in
));
501 getRAnglebracket(in
);
503 //<label name=label1 value=n/>
504 getLAnglebracket(in
);
505 token
= getToken(in
); //"label" or "/"
506 while(strcmp("label",token
) == 0){
507 str
= allocAndCopy(getNameAttribute(in
));
508 token
= getValueStrAttribute(in
);
510 str1
= appendString(str
,"=");
512 str
= appendString(str1
,token
);
514 sequence_push(&(t
->labels
),str
);
516 sequence_push(&(t
->labels
),str
);
519 getRAnglebracket(in
);
521 //next label definition
522 getLAnglebracket(in
);
523 token
= getToken(in
); //"label" or "/"
525 if(strcmp("/",token
))in
->error(in
, "not a valid enum definition");
527 if(strcmp("enum",token
))in
->error(in
, "not a valid enum definition");
528 getRAnglebracket(in
); //</label>
530 else if(strcmp(token
,"int") == 0) {
532 t
->size
= getSizeAttribute(in
);
533 t
->fmt
= allocAndCopy(getFormatAttribute(in
));
535 getRAnglebracket(in
);
537 else if(strcmp(token
,"uint") == 0) {
539 t
->size
= getSizeAttribute(in
);
540 t
->fmt
= allocAndCopy(getFormatAttribute(in
));
542 getRAnglebracket(in
);
544 else if(strcmp(token
,"float") == 0) {
546 t
->size
= getSizeAttribute(in
);
547 t
->fmt
= allocAndCopy(getFormatAttribute(in
));
549 getRAnglebracket(in
);
551 else if(strcmp(token
,"string") == 0) {
553 t
->fmt
= allocAndCopy(getFormatAttribute(in
));
555 getRAnglebracket(in
);
557 else if(strcmp(token
,"typeref") == 0){
558 // Must be a named type
560 in
->error(in
,"Named type cannot refer to a named type");
563 sequence_pop(unnamed_types
);
564 token
= getNameAttribute(in
);
565 t
= find_named_type(token
, named_types
);
566 getForwardslash(in
); //<typeref name=type_name/>
567 getRAnglebracket(in
);
570 }else in
->error(in
,"not a valid type");
575 /*****************************************************************************
577 * find_named_type : find a named type from hash table
580 * named_types : array of named types
582 * type_descriptor * : a type descriptor
583 *****************************************************************************/
585 type_descriptor
* find_named_type(char *name
, table
* named_types
)
589 t
= table_find(named_types
,name
);
591 t
= (type_descriptor
*)memAlloc(sizeof(type_descriptor
));
592 t
->type_name
= allocAndCopy(name
);
595 table_insert(named_types
,t
->type_name
,t
);
596 // table_insert(named_types,allocAndCopy(name),t);
601 /*****************************************************************************
603 * parseTypeDefinition : get type information from type definition
605 * in : input file handle
606 * unnamed_types : array of unamed types
607 * named_types : array of named types
608 *****************************************************************************/
610 void parseTypeDefinition(parse_file
* in
, sequence
* unnamed_types
,
616 token
= getNameAttribute(in
);
617 t
= find_named_type(token
, named_types
);
619 if(t
->type
!= NONE
) in
->error(in
,"redefinition of named type");
620 getRAnglebracket(in
); //<type name=type_name>
621 getLAnglebracket(in
); //<struct>
623 if(strcmp("struct",token
))in
->error(in
,"not a valid type definition");
625 parseType(in
,t
, unnamed_types
, named_types
);
628 getLAnglebracket(in
);
631 if(strcmp("type",token
))in
->error(in
,"not a valid type definition");
632 getRAnglebracket(in
); //</type>
635 /**************************************************************************
637 * getComa, getName, getNumber, getEqual
639 * Read a token from the input file, check its type, return it scontent.
642 * in , input file handle.
645 * address of token content.
647 **************************************************************************/
649 char *getName(parse_file
* in
)
653 token
= getToken(in
);
654 if(in
->type
!= NAME
) in
->error(in
,"Name token was expected");
658 int getNumber(parse_file
* in
)
662 token
= getToken(in
);
663 if(in
->type
!= NUMBER
) in
->error(in
, "Number token was expected");
667 char *getForwardslash(parse_file
* in
)
671 token
= getToken(in
);
672 if(in
->type
!= FORWARDSLASH
) in
->error(in
, "forward slash token was expected");
676 char *getLAnglebracket(parse_file
* in
)
680 token
= getToken(in
);
681 if(in
->type
!= LANGLEBRACKET
) in
->error(in
, "Left angle bracket was expected");
685 char *getRAnglebracket(parse_file
* in
)
689 token
= getToken(in
);
690 if(in
->type
!= RANGLEBRACKET
) in
->error(in
, "Right angle bracket was expected");
694 char *getQuotedString(parse_file
* in
)
698 token
= getToken(in
);
699 if(in
->type
!= QUOTEDSTRING
) in
->error(in
, "quoted string was expected");
703 char * getEqual(parse_file
*in
)
707 token
= getToken(in
);
708 if(in
->type
!= EQUAL
) in
->error(in
, "equal was expected");
712 char seekNextChar(parse_file
*in
)
715 while((car
= getc(in
->fp
)) != EOF
) {
724 /******************************************************************
726 * getToken, ungetToken
728 * Read a token from the input file and return its type and content.
729 * Line numbers are accounted for and whitespace/comments are skipped.
732 * in, input file handle.
735 * address of token content.
737 ******************************************************************/
739 void ungetToken(parse_file
* in
)
744 char *getToken(parse_file
* in
)
748 int pos
= 0, escaped
;
755 /* skip whitespace and comments */
757 while((car
= getc(fp
)) != EOF
) {
760 if(car1
== '*') skipComment(in
);
761 else if(car1
== '/') skipEOL(in
);
763 car1
= ungetc(car1
,fp
);
767 else if(car
== '\n') in
->lineno
++;
768 else if(!isspace(car
)) break;
776 in
->type
= FORWARDSLASH
;
777 in
->buffer
[pos
] = car
;
781 in
->type
= LANGLEBRACKET
;
782 in
->buffer
[pos
] = car
;
786 in
->type
= RANGLEBRACKET
;
787 in
->buffer
[pos
] = car
;
792 in
->buffer
[pos
] = car
;
797 while((car
= getc(fp
)) != EOF
&& pos
< BUFFER_SIZE
) {
798 if(car
== '\\' && escaped
== 0) {
799 in
->buffer
[pos
] = car
;
804 if(car
== '"' && escaped
== 0) break;
805 if(car
== '\n' && escaped
== 0) {
806 in
->error(in
, "non escaped newline inside quoted string");
808 if(car
== '\n') in
->lineno
++;
809 in
->buffer
[pos
] = car
;
813 if(car
== EOF
) in
->error(in
,"no ending quotemark");
814 if(pos
== BUFFER_SIZE
) in
->error(in
, "quoted string token too large");
815 in
->type
= QUOTEDSTRING
;
819 in
->buffer
[pos
] = car
;
821 while((car
= getc(fp
)) != EOF
&& pos
< BUFFER_SIZE
) {
826 in
->buffer
[pos
] = car
;
829 if(car
== EOF
) ungetc(car
,fp
);
830 if(pos
== BUFFER_SIZE
) in
->error(in
, "number token too large");
833 else if(ltt_isalpha(car
)) {
836 while((car
= getc(fp
)) != EOF
&& pos
< BUFFER_SIZE
) {
837 if(!ltt_isalnum(car
)) {
841 in
->buffer
[pos
] = car
;
844 if(car
== EOF
) ungetc(car
,fp
);
845 if(pos
== BUFFER_SIZE
) in
->error(in
, "name token too large");
848 else in
->error(in
, "invalid character, unrecognized token");
854 void skipComment(parse_file
* in
)
857 while((car
= getc(in
->fp
)) != EOF
) {
858 if(car
== '\n') in
->lineno
++;
859 else if(car
== '*') {
862 if(car
== '/') return;
866 if(car
== EOF
) in
->error(in
,"comment begining with '/*' has no ending '*/'");
869 void skipEOL(parse_file
* in
)
872 while((car
= getc(in
->fp
)) != EOF
) {
878 if(car
== EOF
)ungetc(car
, in
->fp
);
881 /*****************************************************************************
883 * checkNamedTypesImplemented : check if all named types have definition
884 * returns -1 on error, 0 if ok
885 ****************************************************************************/
887 int checkNamedTypesImplemented(table
* named_types
)
893 for(pos
= 0 ; pos
< named_types
->values
.position
; pos
++) {
894 t
= (type_descriptor
*) named_types
->values
.array
[pos
];
896 sprintf(str
,"named type '%s' has no definition",
897 (char*)named_types
->keys
.array
[pos
]);
898 error_callback(NULL
,str
);
906 /*****************************************************************************
908 * generateChecksum : generate checksum for the facility
910 * facName : name of facility
912 * checksum : checksum for the facility
913 ****************************************************************************/
915 int generateChecksum(char* facName
, unsigned long * checksum
, sequence
* events
)
922 crc
= crc32(facName
);
923 for(pos
= 0; pos
< events
->position
; pos
++){
924 ev
= (event_t
*)(events
->array
[pos
]);
925 crc
= partial_crc32(ev
->name
,crc
);
926 if(!ev
->type
) continue; //event without type
927 if(ev
->type
->type
!= STRUCT
){
928 sprintf(str
,"event '%s' has a type other than STRUCT",ev
->name
);
929 error_callback(NULL
, str
);
932 crc
= getTypeChecksum(crc
, ev
->type
);
938 /*****************************************************************************
940 * getTypeChecksum : generate checksum by type info
942 * crc : checksum generated so far
943 * type : type descriptor containing type info
945 * unsigned long : checksum
946 *****************************************************************************/
948 unsigned long getTypeChecksum(unsigned long aCrc
, type_descriptor
* type
)
950 unsigned long crc
= aCrc
;
951 char * str
= NULL
, buf
[16];
957 str
= intOutputTypes
[type
->size
];
960 str
= uintOutputTypes
[type
->size
];
963 str
= floatOutputTypes
[type
->size
];
966 str
= allocAndCopy("string");
970 str
= appendString("enum ", uintOutputTypes
[type
->size
]);
974 sprintf(buf
,"%d",type
->size
);
975 str
= appendString("array ",buf
);
979 sprintf(buf
,"%d",type
->size
);
980 str
= appendString("sequence ",buf
);
984 str
= allocAndCopy("struct");
988 str
= allocAndCopy("union");
992 error_callback(NULL
, "named type has no definition");
996 crc
= partial_crc32(str
,crc
);
999 if(type
->fmt
) crc
= partial_crc32(type
->fmt
,crc
);
1001 if(type
->type
== ARRAY
|| type
->type
== SEQUENCE
){
1002 crc
= getTypeChecksum(crc
,type
->nested_type
);
1003 }else if(type
->type
== STRUCT
|| type
->type
== UNION
){
1004 for(pos
=0; pos
< type
->fields
.position
; pos
++){
1005 fld
= (type_fields
*) type
->fields
.array
[pos
];
1006 crc
= partial_crc32(fld
->name
,crc
);
1007 crc
= getTypeChecksum(crc
, fld
->type
);
1009 }else if(type
->type
== ENUM
){
1010 for(pos
= 0; pos
< type
->labels
.position
; pos
++)
1011 crc
= partial_crc32((char*)type
->labels
.array
[pos
],crc
);
1018 /* Event type descriptors */
1019 void freeType(type_descriptor
* tp
)
1024 if(tp
->fmt
!= NULL
) free(tp
->fmt
);
1025 if(tp
->type
== ENUM
) {
1026 for(pos2
= 0; pos2
< tp
->labels
.position
; pos2
++) {
1027 free(tp
->labels
.array
[pos2
]);
1029 sequence_dispose(&(tp
->labels
));
1031 if(tp
->type
== STRUCT
) {
1032 for(pos2
= 0; pos2
< tp
->fields
.position
; pos2
++) {
1033 f
= (type_fields
*) tp
->fields
.array
[pos2
];
1035 free(f
->description
);
1038 sequence_dispose(&(tp
->fields
));
1042 void freeNamedType(table
* t
)
1045 type_descriptor
* td
;
1047 for(pos
= 0 ; pos
< t
->keys
.position
; pos
++) {
1048 free((char *)t
->keys
.array
[pos
]);
1049 td
= (type_descriptor
*)t
->values
.array
[pos
];
1055 void freeTypes(sequence
*t
)
1058 type_descriptor
*tp
;
1060 for(pos
= 0 ; pos
< t
->position
; pos
++) {
1061 tp
= (type_descriptor
*)t
->array
[pos
];
1067 void freeEvents(sequence
*t
)
1072 for(pos
= 0 ; pos
< t
->position
; pos
++) {
1073 ev
= (event_t
*) t
->array
[pos
];
1075 free(ev
->description
);
1082 /* Extensible array */
1084 void sequence_init(sequence
*t
)
1088 t
->array
= (void **)memAlloc(t
->size
* sizeof(void *));
1091 void sequence_dispose(sequence
*t
)
1098 void sequence_push(sequence
*t
, void *elem
)
1102 if(t
->position
>= t
->size
) {
1104 t
->array
= (void **)memAlloc(t
->size
* 2 * sizeof(void *));
1105 memcpy(t
->array
, tmp
, t
->size
* sizeof(void *));
1106 t
->size
= t
->size
* 2;
1109 t
->array
[t
->position
] = elem
;
1113 void *sequence_pop(sequence
*t
)
1115 return t
->array
[t
->position
--];
1119 /* Hash table API, implementation is just linear search for now */
1121 void table_init(table
*t
)
1123 sequence_init(&(t
->keys
));
1124 sequence_init(&(t
->values
));
1127 void table_dispose(table
*t
)
1129 sequence_dispose(&(t
->keys
));
1130 sequence_dispose(&(t
->values
));
1133 void table_insert(table
*t
, char *key
, void *value
)
1135 sequence_push(&(t
->keys
),key
);
1136 sequence_push(&(t
->values
),value
);
1139 void *table_find(table
*t
, char *key
)
1142 for(pos
= 0 ; pos
< t
->keys
.position
; pos
++) {
1143 if(strcmp((char *)key
,(char *)t
->keys
.array
[pos
]) == 0)
1144 return(t
->values
.array
[pos
]);
1149 void table_insert_int(table
*t
, int *key
, void *value
)
1151 sequence_push(&(t
->keys
),key
);
1152 sequence_push(&(t
->values
),value
);
1155 void *table_find_int(table
*t
, int *key
)
1158 for(pos
= 0 ; pos
< t
->keys
.position
; pos
++) {
1159 if(*key
== *(int *)t
->keys
.array
[pos
])
1160 return(t
->values
.array
[pos
]);
1166 /* Concatenate strings */
1168 char *appendString(char *s
, char *suffix
)
1171 if(suffix
== NULL
) return s
;
1173 tmp
= (char *)memAlloc(strlen(s
) + strlen(suffix
) + 1);
This page took 0.05328 seconds and 4 git commands to generate.