1 : /*
2 : * This file is part of MIN Test Framework. Copyright © 2008 Nokia Corporation
3 : * and/or its subsidiary(-ies).
4 : * Contact: Konrad Marek Zapalowicz
5 : * Contact e-mail: DG.MIN-Support@nokia.com
6 : *
7 : * This program is free software: you can redistribute it and/or modify it
8 : * under the terms of the GNU General Public License as published by the Free
9 : * Software Foundation, version 2 of the License.
10 : *
11 : * This program is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 : * more details. You should have received a copy of the GNU General Public
15 : * License along with this program. If not, see
16 : * <http://www.gnu.org/licenses/>.
17 : */
18 :
19 :
20 : /**
21 : * @file min_file_parser.c
22 : * @version 0.1
23 : * @brief This file contains implementation of Min File Parser
24 : */
25 :
26 : /* ------------------------------------------------------------------------- */
27 : /* INCLUDE FILES */
28 : #include <unistd.h>
29 : #include "min_file_parser.h"
30 :
31 : /* ------------------------------------------------------------------------- */
32 : /* EXTERNAL DATA STRUCTURES */
33 : /* None */
34 :
35 : /* ------------------------------------------------------------------------- */
36 : /* EXTERNAL GLOBAL VARIABLES */
37 : /* None */
38 :
39 : /* ------------------------------------------------------------------------- */
40 : /* EXTERNAL FUNCTION PROTOTYPES */
41 : /* None */
42 :
43 : /* ------------------------------------------------------------------------- */
44 : /* GLOBAL VARIABLES */
45 : /* None */
46 :
47 : /* ------------------------------------------------------------------------- */
48 : /* CONSTANTS */
49 : /* None */
50 :
51 : /* ------------------------------------------------------------------------- */
52 : /* MACROS */
53 : /*#define MIN_UNIT_TEST*/
54 :
55 : /* ------------------------------------------------------------------------- */
56 : /* LOCAL GLOBAL VARIABLES */
57 : /* ------------------------------------------------------------------------- */
58 : /* LOCAL CONSTANTS AND MACROS */
59 : /* None */
60 :
61 : /* ------------------------------------------------------------------------- */
62 : /* MODULE DATA STRUCTURES */
63 : /* None */
64 :
65 : /* ------------------------------------------------------------------------- */
66 : /* LOCAL FUNCTION PROTOTYPES */
67 : /* ------------------------------------------------------------------------- */
68 : /** Reads configuration source and returns a complete line.
69 : * This method will return also and end of line sequence.
70 : * @param line_buffer [out] handler to which the buffer will be attached.
71 : * @param eol_buffer [out] table for eol sequence.
72 : * @return > 0 on success, 0 on failure.
73 : */
74 : LOCAL TSBool mfp_read_line (MinFileParser * sfp,
75 : TSChar ** line_buffer, TSChar * eol_buffer);
76 : /* ------------------------------------------------------------------------- */
77 : /**
78 : * Parses a given line and removes all c-style comments from it.
79 : * Result is passed in destination buffer.
80 : * @param src_buff [in] buffer to be processed.
81 : * @param dst_buff [out] the result of processing.
82 : * @param find [in] what kind of comments we are looking for.
83 : */
84 : LOCAL void mfp_replace_comments_line (const TSChar * src_buff,
85 : TSChar ** dst_buff,
86 : TWhatToFind find);
87 : /* ------------------------------------------------------------------------- */
88 : /**
89 : * Parses a given line and removes all #-style comments.
90 : * Result is passed in destination buffer.
91 : * @param src_buff [in] buffer to be processed.
92 : * @param dst_buff [out] the result of processing.
93 : */
94 : LOCAL void mfp_replace_hash_comments_line (const TSChar * src_buff,
95 : TSChar ** dst_buff);
96 : /* ------------------------------------------------------------------------- */
97 : /** Closes all files on file stack and clears the stack.
98 : * @param sfp [in] pointer to the MinFileParser to operate on.
99 : */
100 : LOCAL void mfp_clear_file_stack (MinFileParser * sfp);
101 : /* ------------------------------------------------------------------------- */
102 : /** Pops FILE handle from file stack and sets correct current file handle.
103 : * @param sfp [in] pointer to the MinFileParser to operate on.
104 : */
105 : LOCAL void mfp_pop_from_file_stack (MinFileParser * sfp);
106 : /* ------------------------------------------------------------------------- */
107 : /** Opens file and pushes it to stack.
108 : * @param sfp [in] pointer to the MinFileParser to operate on.
109 : * @param file_name [in] value to be pushed to the stack.
110 : */
111 : LOCAL void mfp_push_file_to_stack (MinFileParser * sfp,
112 : const TSChar * file_name);
113 : /* ------------------------------------------------------------------------- */
114 : /** Deletes all descriptors assigned to array and empties array.
115 : * @param sfp [in] pointer to the MinFileParser to operate on.
116 : */
117 : /* LOCAL void clear_section_lines_array( MinFileParser* sfp );missing -ssaa */
118 : /* ------------------------------------------------------------------------- */
119 : /** Used for comparing filenames on the list */
120 : LOCAL int compare_filename (const void *a, const void *b);
121 : /* ------------------------------------------------------------------------- */
122 : /* FORWARD DECLARATIONS */
123 : /* None */
124 :
125 : /* ------------------------------------------------------------------------- */
126 : /* ==================== LOCAL FUNCTIONS ==================================== */
127 : /* ------------------------------------------------------------------------- */
128 : LOCAL int compare_filename (const void *a, const void *b)
129 26 : {
130 : int retval =
131 26 : strcmp ((const TSChar *)a, (const TSChar *)b);
132 :
133 26 : if (retval == 0)
134 6 : return 0;
135 20 : if (retval < 0)
136 9 : return -1;
137 11 : if (retval > 0)
138 11 : return 1;
139 :
140 0 : return retval;
141 : }
142 :
143 : /* ------------------------------------------------------------------------- */
144 : LOCAL TSBool mfp_read_line (MinFileParser * sfp, TSChar ** line_buffer,
145 : TSChar * eol_buffer)
146 122595 : {
147 122595 : TSBool retval = ESFalse;
148 122595 : Text *buf = tx_create ("");
149 122595 : TSChar *c = INITPTR;
150 : TSChar tmp[2];
151 122595 : tmp[0] = '\0';
152 122595 : tmp[1] = '\0';
153 :
154 122595 : if (sfp == INITPTR) {
155 2 : errno = EINVAL;
156 2 : return retval;
157 : }
158 122593 : if (eol_buffer == INITPTR) {
159 0 : errno = EINVAL;
160 0 : return retval;
161 : }
162 :
163 : /* Reset eol buffer */
164 122593 : eol_buffer[0] = '\0';
165 122593 : eol_buffer[1] = '\0';
166 122593 : eol_buffer[2] = '\0';
167 :
168 : /* 1. Read whole line, char by char till endline character is meet */
169 : while (1) {
170 1747281 : tmp[0] = (TSChar) getc (sfp->current_file_);
171 :
172 1747281 : if (tmp[0] == '\n') {
173 :
174 : /* It is newline, so we have to check if line contains
175 : * INCLUDE keyword
176 : */
177 122348 : eol_buffer[0] = '\n';
178 122348 : c = strstr (buf->buf_, "INCLUDE");
179 122348 : if (c != NULL) {
180 0 : c += 7;
181 0 : while (strchr (" \n\t\r", *c) != NULL) {
182 0 : c++;
183 : }
184 0 : if (strlen (c) > 0) {
185 0 : mfp_push_file_to_stack (sfp, c);
186 0 : sfp->eol_buff_[0] = eol_buffer[0];
187 0 : sfp->eol_buff_[1] = eol_buffer[1];
188 0 : sfp->eol_buff_[2] = eol_buffer[2];
189 : }
190 : }
191 :
192 122348 : retval = ESTrue;
193 122348 : break;
194 :
195 1624933 : } else if (((char)tmp[0] == (char)EOF) || feof (sfp->current_file_)) {
196 :
197 245 : if (dl_list_size (sfp->file_stack_) > 0) {
198 : /* Try to pop file from stack */
199 0 : mfp_pop_from_file_stack (sfp);
200 0 : retval = ESTrue;
201 : } else {
202 245 : if (strlen (buf->buf_) > 0)
203 0 : retval = ESTrue;
204 : else
205 245 : retval = ESFalse;
206 245 : break;
207 : }
208 : }
209 :
210 1624688 : tx_c_append (buf, tmp);
211 1624688 : }
212 122593 : if (retval == ESTrue) {
213 122348 : tx_back_trim (buf, " \n\r\t");
214 122348 : *line_buffer = tx_get_buf (buf);
215 122348 : tx_destroy (&buf);
216 : }
217 : else {
218 245 : *line_buffer = INITPTR;
219 245 : tx_destroy (&buf);
220 : }
221 122593 : return retval;
222 : }
223 :
224 : /* ------------------------------------------------------------------------- */
225 : LOCAL void mfp_replace_comments_line (const TSChar * src_buff,
226 : TSChar ** dst_buff, TWhatToFind find)
227 7 : {
228 :
229 : const TSChar *c;
230 : TSChar *buff;
231 : TSChar *cc;
232 : int len;
233 : TSChar space, slash, quota, multi, hash, append[2];
234 :
235 7 : if (src_buff == INITPTR)
236 1 : return;
237 :
238 6 : c = &src_buff[0];
239 6 : buff = NEW2 (TSChar, strlen (src_buff) + 1);
240 6 : cc = &buff[0];
241 6 : len = 0;
242 6 : space = ' ';
243 6 : slash = '/';
244 6 : quota = '\"';
245 6 : multi = '*';
246 6 : hash = '#';
247 6 : append[0] = '\0';
248 6 : append[1] = '\0';
249 :
250 139 : while (*c != '\0') {
251 :
252 : /* We're looking for start of quoted text or comment */
253 128 : if (find == EStart) {
254 :
255 49 : if (*c == quota) {
256 4 : find = EQuota;
257 4 : append[0] = space;
258 4 : STRCPY (cc, append, strlen (append));
259 4 : cc = cc + strlen (append);
260 45 : } else if (*c == slash) {
261 2 : if (*(c + 1) == slash) {
262 : /* Comment to the end of
263 : line found */
264 1 : break;
265 1 : } else if (*(c + 1) == multi) {
266 : /* Beginning of a comment found */
267 1 : find = EEndOfComment;
268 1 : c++;
269 1 : append[0] = space;
270 1 : STRCPY (cc, append, strlen (append));
271 1 : cc = cc + strlen (append);
272 1 : STRCPY (cc, append, strlen (append));
273 1 : cc = cc + strlen (append);
274 : } else {
275 : /* No start of comment - add read
276 : slash */
277 0 : append[0] = *c;
278 0 : STRCPY (cc, append, strlen (append));
279 0 : cc = cc + strlen (append);
280 : }
281 43 : } else if (*c == hash) {
282 : /* Start of hash comment
283 : (to the end of line) */
284 0 : break;
285 : } else {
286 : /* Append readed TSCharacter to the destination
287 : buffer */
288 43 : append[0] = *c;
289 43 : STRCPY (cc, append, strlen (append));
290 43 : cc = cc + strlen (append);
291 : }
292 :
293 79 : } else if (find == EQuota) {
294 : /* We're looking for the end of quoted text */
295 73 : if (*c == quota) {
296 4 : find = EStart;
297 : }
298 73 : append[0] = space;
299 73 : STRCPY (cc, append, strlen (append));
300 73 : cc = cc + strlen (append);
301 6 : } else if (find == EEndOfComment) {
302 : /* We're looking for the end of comment */
303 6 : if (*c == multi) {
304 : /* It may be the end of a comment */
305 1 : if (*(c + 1) == slash) {
306 : /* It is the end of a comment */
307 1 : find = EStart;
308 1 : c++;
309 1 : append[0] = space;
310 1 : STRCPY (cc, append, strlen (append));
311 1 : cc = cc + strlen (append);
312 1 : STRCPY (cc, append, strlen (append));
313 1 : cc = cc + strlen (append);
314 : } else {
315 : /* It is not the end of a comment,
316 : add this TSCharacter to the
317 : destinaton buffer */
318 0 : append[0] = *c;
319 0 : STRCPY (cc, append, strlen (append));
320 0 : cc = cc + strlen (append);
321 : }
322 : } else {
323 : /* It is not the end of a comment,
324 : add this TSCharacter to the destinaton
325 : buffer */
326 5 : append[0] = space;
327 5 : STRCPY (cc, append, strlen (append));
328 5 : cc = cc + strlen (append);
329 : }
330 : }
331 127 : c++;
332 : }
333 :
334 6 : c = &buff[0];
335 :
336 41 : while (*c == ' ' && c != cc) {
337 29 : c++;
338 : }
339 6 : cc--;
340 59 : while (*cc == ' ' && cc + 1 != c) {
341 47 : cc--;
342 : }
343 :
344 6 : if (cc == &buff[0])
345 0 : *(cc) = '\0';
346 : else
347 6 : *(cc + 1) = '\0';
348 :
349 6 : len = strlen (c);
350 :
351 6 : *dst_buff = NEW2 (TSChar, len + 2);
352 6 : STRCPY (*dst_buff, c, len + 1);
353 6 : (*dst_buff)[len] = '\0';
354 :
355 6 : free (buff);
356 : }
357 :
358 : /* ------------------------------------------------------------------------- */
359 : LOCAL void mfp_replace_hash_comments_line (const TSChar * src_buff,
360 : TSChar ** dst_buff)
361 122347 : {
362 :
363 : const TSChar *c;
364 : TSChar *buff;
365 : TSChar *cc;
366 : TSChar hash;
367 : TSChar append[2];
368 :
369 122347 : if (src_buff == INITPTR)
370 1 : return;
371 :
372 122346 : c = &src_buff[0];
373 122346 : buff = NEW2 (TSChar, strlen (src_buff) + 1);
374 122346 : cc = &buff[0];
375 122346 : hash = '#';
376 122346 : append[0] = '\0';
377 122346 : append[1] = '\0';
378 :
379 1828487 : while (*c != '\0') {
380 :
381 1588887 : if (*c == hash)
382 5092 : break;
383 : else {
384 1583795 : append[0] = *c;
385 1583795 : STRCPY (cc, append, strlen (append));
386 1583795 : cc = cc + strlen (append);
387 : }
388 1583795 : c++;
389 : }
390 :
391 122346 : append[0] = '\0';
392 122346 : STRCPY (cc, append, strlen (append));
393 122346 : cc = cc + strlen (append);
394 :
395 : /* Point buff to the output */
396 122346 : *dst_buff = buff;
397 : }
398 :
399 : /* ------------------------------------------------------------------------- */
400 : LOCAL void mfp_clear_file_stack (MinFileParser * sfp)
401 235 : {
402 235 : if (sfp == INITPTR) {
403 1 : errno = EINVAL;
404 1 : goto EXIT;
405 : }
406 :
407 470 : while (dl_list_size (sfp->file_stack_) != 0) {
408 2 : mfp_pop_from_file_stack (sfp);
409 : }
410 235 : EXIT:
411 : return;
412 : }
413 :
414 : /* ------------------------------------------------------------------------- */
415 : LOCAL void mfp_pop_from_file_stack (MinFileParser * sfp)
416 9 : {
417 9 : DLListIterator it = DLListNULLIterator;
418 9 : DLListIterator it2 = DLListNULLIterator;
419 : TSChar file[4096];
420 : TSChar buf[64];
421 : ssize_t rval;
422 :
423 9 : if (sfp == INITPTR) {
424 1 : errno = EINVAL;
425 1 : goto EXIT;
426 : }
427 8 : if (dl_list_size (sfp->file_stack_) == 0) {
428 1 : goto EXIT;
429 : }
430 :
431 : /* prepare table */
432 7 : memset (file, 0x0, 4096);
433 :
434 : /* Pop from stack */
435 7 : it = dl_list_tail (sfp->file_stack_);
436 7 : sfp->current_file_ = (FILE *) dl_list_data (it);
437 7 : dl_list_remove_it (it);
438 :
439 : /* Lets get filename associated with this descriptor */
440 7 : sprintf (buf, "/proc/self/fd/%d", fileno (sfp->current_file_));
441 7 : rval = readlink (buf, &file[0], 4095);
442 7 : if (rval < 0) {
443 0 : return;
444 : }
445 : /* Remove from file names list */
446 7 : it2 = dl_list_find (dl_list_head (sfp->file_names_)
447 : , dl_list_tail (sfp->file_names_)
448 : , compare_filename, file);
449 :
450 7 : if (it2 != DLListNULLIterator) {
451 5 : dl_list_remove_it (it2);
452 : }
453 :
454 : /* Close file */
455 7 : fclose (sfp->current_file_);
456 :
457 : /* Set correct current file */
458 7 : if (dl_list_size (sfp->file_stack_) == 0) {
459 4 : sfp->current_file_ = sfp->base_file_;
460 : } else {
461 3 : it = dl_list_tail (sfp->file_stack_);
462 3 : sfp->current_file_ = (FILE *) dl_list_data (it);
463 : }
464 : /* Lets get filename associated with this descriptor */
465 7 : memset (file, 0x0, 4096);
466 7 : memset (buf, 0x0, 64);
467 7 : sprintf (buf, "/proc/self/fd/%d", fileno (sfp->current_file_));
468 7 : rval = readlink (buf, &file[0], 4095);
469 :
470 9 : EXIT:
471 9 : return;
472 : }
473 :
474 : /* ------------------------------------------------------------------------- */
475 : LOCAL void mfp_push_file_to_stack (MinFileParser * sfp,
476 : const TSChar * file_name)
477 10 : {
478 10 : DLListIterator it = DLListNULLIterator;
479 10 : FILE *fp = INITPTR;
480 :
481 10 : if (sfp == INITPTR) {
482 1 : errno = EINVAL;
483 1 : goto EXIT;
484 : }
485 9 : if (file_name == INITPTR) {
486 1 : errno = EINVAL;
487 1 : goto EXIT;
488 : }
489 :
490 : /* Check if file is not laready included */
491 8 : it = dl_list_find (dl_list_head (sfp->file_names_)
492 : , dl_list_tail (sfp->file_names_)
493 : , compare_filename, (const void *)file_name);
494 :
495 8 : if (it != DLListNULLIterator) {
496 1 : goto EXIT;
497 : }
498 :
499 : /* Open file */
500 7 : fp = fopen (file_name, "r");
501 :
502 7 : if (fp == NULL) {
503 3 : goto EXIT;
504 : }
505 :
506 : /* Add to stack */
507 4 : dl_list_add (sfp->file_stack_, (void *)fp);
508 :
509 : /* Add name to names array */
510 4 : dl_list_add (sfp->file_names_, (void *)file_name);
511 :
512 : /* Set current file */
513 4 : sfp->current_file_ = fp;
514 :
515 10 : EXIT:
516 : return;
517 : }
518 :
519 : /* ------------------------------------------------------------------------- */
520 : /* ======================== FUNCTIONS ====================================== */
521 : /* ------------------------------------------------------------------------- */
522 : MinFileParser *mfp_create (FILE * file, TUnicode is_unicode,
523 : TCommentType comment_type)
524 289 : {
525 289 : MinFileParser *tmp = INITPTR;
526 : TSChar path[4096];
527 : TSChar buf[64];
528 : ssize_t rval;
529 :
530 289 : if (file == INITPTR) {
531 1 : errno = EINVAL;
532 1 : goto EXIT;
533 : }
534 288 : if (file == NULL) {
535 1 : errno = EINVAL;
536 1 : goto EXIT;
537 : }
538 :
539 : /* Initialize */
540 287 : tmp = NEW (MinFileParser);
541 287 : tmp->base_file_ = file;
542 287 : tmp->comment_type_ = comment_type;
543 287 : tmp->is_unicode_ = is_unicode;
544 287 : tmp->bytes_per_char_ = tmp->is_unicode_ ? 2 : 1;
545 287 : tmp->current_file_ = tmp->base_file_;
546 287 : tmp->section_lines_ = INITPTR; /* dl_list_create();
547 : mfp_read_line() creates */
548 287 : tmp->file_stack_ = dl_list_create ();
549 287 : tmp->file_names_ = dl_list_create ();
550 287 : tmp->eol_buff_[0] = '\0';
551 287 : tmp->eol_buff_[1] = '\0';
552 287 : tmp->eol_buff_[2] = '\0';
553 :
554 : /* prepare table */
555 287 : memset (path, 0x0, 4096);
556 :
557 : /* Lets get filename associated with this descriptor */
558 287 : sprintf (buf, "/proc/self/fd/%d", fileno (file));
559 287 : rval = readlink (buf, &path[0], 4095);
560 287 : if (rval < 0) {
561 0 : return NULL;
562 : }
563 :
564 : /* Add base file to the file names array */
565 287 : dl_list_add (tmp->file_names_, path);
566 289 : EXIT:
567 289 : return tmp;
568 : }
569 :
570 : /* ------------------------------------------------------------------------- */
571 : void mfp_destroy (MinFileParser ** sfp)
572 270 : {
573 270 : if (*sfp == INITPTR)
574 39 : return;
575 :
576 231 : mfp_clear_file_stack (*sfp);
577 :
578 231 : if ((*sfp)->section_lines_ != INITPTR) {
579 0 : dl_list_free_data (&((*sfp)->section_lines_));
580 0 : dl_list_free (&((*sfp)->section_lines_));
581 : }
582 231 : dl_list_free_data (&((*sfp)->file_stack_));
583 231 : dl_list_free (&((*sfp)->file_stack_));
584 :
585 231 : dl_list_free (&((*sfp)->file_names_));
586 :
587 231 : free (*sfp);
588 231 : *sfp = INITPTR;
589 : }
590 :
591 : /* ------------------------------------------------------------------------- */
592 : TSChar *mfp_next_section (MinFileParser * sfp,
593 : const TSChar * start_tag,
594 : const TSChar * end_tag, int *offset,
595 : int seeked)
596 1475 : {
597 1475 : TSChar *retval = INITPTR;
598 1475 : int found_section = 0;
599 1475 : int ret = 0;
600 1475 : int size = 0;
601 1475 : TSChar *buff = INITPTR;
602 1475 : TSChar *without_comments_buff = INITPTR;
603 1475 : TSChar *line = INITPTR;
604 : TSChar end_of_line_buff[3];
605 1475 : int validSectionBeginFound = 0;
606 1475 : int validSectionEndFound = 0;
607 1475 : TSectionFind whatToFindSection = ESectionStart;
608 1475 : TWhatToFind whatToFind = EStart;
609 1475 : DLListIterator it = DLListNULLIterator;
610 1475 : int buff_len = 0;
611 :
612 1475 : if (seeked < 1) {
613 8 : errno = EINVAL;
614 8 : goto EXIT;
615 : }
616 1467 : if (*offset < 0) {
617 1 : errno = EINVAL;
618 1 : goto EXIT;
619 : }
620 1466 : if (sfp == INITPTR) {
621 1 : errno = EINVAL;
622 1 : goto EXIT;
623 : }
624 1465 : if (start_tag == INITPTR) {
625 1 : errno = EINVAL;
626 1 : goto EXIT;
627 : }
628 1464 : if (end_tag == INITPTR) {
629 1 : errno = EINVAL;
630 1 : goto EXIT;
631 : }
632 1463 : end_of_line_buff[0] = '\0';
633 1463 : end_of_line_buff[1] = '\0';
634 1463 : end_of_line_buff[2] = '\0';
635 :
636 1463 : sfp->section_lines_ = dl_list_create ();
637 :
638 1463 : if (*offset == 0) {
639 : /* Set valid position in file
640 : but only if offset shows to 0. Otherwise keep previous
641 : position */
642 1463 : fseek (sfp->current_file_, 0L, SEEK_SET);
643 : /*rewind( sfp->current_file_ ); */
644 1463 : *offset = 1;
645 : }
646 :
647 : /* If no start tag is given start to find end tag immediatly */
648 1463 : if (strlen (start_tag) == 0) {
649 0 : found_section++;
650 0 : whatToFindSection = ESectionEnd;
651 0 : validSectionBeginFound = 1;
652 : }
653 1463 : if (strlen (end_tag) == 0)
654 0 : validSectionEndFound = 1;
655 :
656 : /* Perform reading file */
657 124048 : while (mfp_read_line (sfp, &buff, end_of_line_buff) != ESFalse) {
658 :
659 122340 : if (sfp->comment_type_ == ECStyleComments) {
660 0 : mfp_replace_comments_line (buff,
661 : &without_comments_buff,
662 : whatToFind);
663 : } else {
664 122340 : mfp_replace_hash_comments_line (buff,
665 : &without_comments_buff);
666 : }
667 :
668 122340 : if (whatToFindSection == ESectionStart) {
669 : /* Find in line star tag (if start tag is not given,
670 : behave like we've found it) */
671 42399 : if (strstr (without_comments_buff, start_tag) != NULL)
672 13220 : ret = 0;
673 : else
674 29179 : ret = -1;
675 :
676 42399 : if (ret >= 0) {
677 :
678 13220 : whatToFindSection = ESectionEnd;
679 13220 : whatToFind = EStart; /* reset marker */
680 13220 : found_section++;
681 :
682 : /* Add this line to section lines array */
683 13220 : if (found_section == seeked) {
684 :
685 : /* Add start tag if line
686 : * contains something more
687 : * than just a start tag. */
688 1218 : if (strlen (start_tag) <
689 : strlen (without_comments_buff)) {
690 0 : buff_len =
691 : strlen
692 : (without_comments_buff) +
693 : 1;
694 :
695 0 : line =
696 : NEW2 (TSChar,
697 : buff_len +
698 : strlen
699 : (end_of_line_buff) +
700 : 1);
701 :
702 0 : STRCPY (line,
703 : without_comments_buff,
704 : buff_len);
705 :
706 0 : STRCPY (&line[buff_len - 1]
707 : , &end_of_line_buff[0]
708 : ,
709 : strlen
710 : (end_of_line_buff) +
711 : 2);
712 :
713 0 : dl_list_add (sfp->
714 : section_lines_,
715 : (void *)line);
716 : }
717 1218 : validSectionBeginFound = 1;
718 : }
719 13220 : goto loopend;
720 : }
721 79941 : } else if (whatToFindSection == ESectionEnd) {
722 : /* Find in line star tag (if start tag is not given,
723 : behave like we've found it) */
724 :
725 79941 : if (strstr (without_comments_buff, end_tag) != NULL)
726 13220 : ret = 0;
727 : else
728 66721 : ret = -1;
729 :
730 79941 : if (ret >= 0) {
731 :
732 :
733 13220 : whatToFindSection = ESectionStart;
734 13220 : whatToFind = EStart; /* reset marker */
735 :
736 13220 : if (found_section == seeked) {
737 : /* Add this line to
738 : * section lines array */
739 1218 : if (strlen (end_tag) <
740 : strlen (without_comments_buff)) {
741 0 : buff_len =
742 : strlen
743 : (without_comments_buff) +
744 : 1;
745 :
746 : TSChar *line =
747 0 : NEW2 (TSChar,
748 : buff_len +
749 : strlen
750 : (end_of_line_buff) +
751 : 1);
752 0 : STRCPY (line,
753 : without_comments_buff,
754 : buff_len);
755 :
756 0 : STRCPY (&line[buff_len - 1]
757 : , &end_of_line_buff[0]
758 : ,
759 : strlen
760 : (end_of_line_buff) +
761 : 2);
762 :
763 0 : dl_list_add (sfp->
764 : section_lines_,
765 : (void *)line);
766 : }
767 1218 : validSectionEndFound = 1;
768 1218 : DELETE (buff);
769 1218 : DELETE (without_comments_buff);
770 1218 : break;
771 : } else {
772 12002 : goto loopend;
773 : }
774 : } else {
775 : /* If we're in section we are looking for,
776 : * add line to array */
777 66721 : if (found_section == seeked) {
778 :
779 :
780 6691 : buff_len =
781 : strlen (without_comments_buff) +
782 : 1;
783 :
784 6691 : line =
785 : NEW2 (TSChar,
786 : buff_len +
787 : strlen (end_of_line_buff) +
788 : 1);
789 :
790 6691 : STRCPY (line, without_comments_buff,
791 : buff_len);
792 :
793 6691 : STRCPY (&line[buff_len - 1]
794 : , &end_of_line_buff[0]
795 : ,
796 : strlen (end_of_line_buff) +
797 : 2);
798 :
799 6691 : dl_list_add (sfp->section_lines_,
800 : (void *)line);
801 : }
802 : }
803 : }
804 121122 : loopend:
805 : /* Clean data */
806 121122 : DELETE (buff);
807 121122 : DELETE (without_comments_buff);
808 :
809 : } /* while */
810 :
811 : /* Load into section if found */
812 1463 : if (validSectionBeginFound && validSectionEndFound) {
813 : /* Count amount of memory needed for section */
814 1218 : it = dl_list_head (sfp->section_lines_);
815 :
816 9127 : while (it != DLListNULLIterator) {
817 6691 : TSChar *tmp = (TSChar *) dl_list_data (it);
818 6691 : size += strlen (tmp);
819 6691 : it = dl_list_next (it);
820 :
821 : /* Do not copy last line that contains end tag */
822 : //if( dl_list_next(it) == INITPTR ) { break; }
823 : }
824 :
825 : /* Copy section from array to buffer */
826 1218 : retval = NEW2 (TSChar, size + 2);
827 1218 : retval[size + 1] = '\0';
828 1218 : buff = &retval[0];
829 :
830 1218 : it = dl_list_head (sfp->section_lines_);
831 9127 : while (it != DLListNULLIterator) {
832 6691 : TSChar *tmp = (TSChar *) dl_list_data (it);
833 :
834 :
835 6691 : STRCPY (buff, tmp, strlen (tmp) + 1);
836 :
837 6691 : buff += strlen (tmp);
838 6691 : it = dl_list_next (it);
839 :
840 : /* Do not copy last line that contains end tag */
841 : //if( dl_list_next(it) == INITPTR ) { break; }
842 : }
843 : }
844 :
845 : /* Clean */
846 1463 : it = dl_list_head (sfp->section_lines_);
847 9617 : while (it != DLListNULLIterator) {
848 6691 : free (it->data_);
849 6691 : it = dl_list_next (it);
850 : }
851 :
852 1463 : dl_list_free (&sfp->section_lines_);
853 :
854 1475 : EXIT:
855 1475 : return retval;
856 : }
857 :
858 : /* ------------------------------------------------------------------------- */
859 : /* ================= OTHER EXPORTED FUNCTIONS ============================== */
860 : /* None */
861 :
862 :
863 : /* ================= TESTS FOR LOCAL FUNCTIONS ============================= */
864 : #ifdef MIN_UNIT_TEST
865 : #include "min_file_parser.tests"
866 : #endif /* MIN_UNIT_TEST */
867 : /* ------------------------------------------------------------------------- */
868 : /* End of file */
|