2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: parse_c.c /main/4 1996/10/02 13:32:03 drk $ */
27 * Parses a C file for stubs merge.
31 #define _POSIX_SOURCE 1
38 #include <ab_private/AB.h>
39 #include <ab_private/util_err.h>
40 #include <ab/util_types.h>
41 #include <ab_private/util.h>
42 #include <ab_private/abio.h>
45 /* DTB_USER_CODE_START */
46 /* DTB_USER_CODE_END*/
48 #define MAX_USER_SEGS_PER_SEG 10
59 /* the offsets of the last 2 newlines read from the file */
63 /* DTB_USER_CODE_START */
66 /* DTB_USER_CODE_END */
75 } BFileStateRec, *BFileState;
77 static int bfile_construct(BFile, FILE *file);
78 static int bfile_destruct(BFile);
79 static BOOL bfile_is_forward(BFile file);
80 static BOOL bfile_is_reverse(BFile file);
81 static int bfile_get_char(BFile);
82 static int bfile_backup(BFile, long numBytes);
83 static long bfile_get_off(BFile);
84 static int bfile_set_off(BFile, long off);
85 static BOOL bfile_eof(BFile);
86 static int bfile_set_file(BFile, FILE *stream);
87 static int bfile_reverse(BFile);
88 static int bfile_forward(BFile);
89 static int bfile_save_state(BFile, BFileState);
90 static int bfile_restore_state(BFile, BFileState);
98 COMMENT_TYPE_NUM_VALUES
105 MAGIC_CMT_USER_START,
107 MAGIC_COMMENT_TYPE_NUM_VALUES /* must be last */
108 } MAGIC_COMMENT_TYPE;
109 #define MAGIC_COMMENT_MAX_LEN (20)
110 #define MAGIC_COMMENT_MAX_SIZE (MAGIC_COMMENT_MAX_LEN+1)
112 static STRING magicCommentUserStart = "DTB_USER_CODE_START";
113 static STRING magicCommentUserEnd = "DTB_USER_CODE_END";
116 static int write_func_var_decl(FILE *file, CSeg cseg);
117 static int write_func_as_strings(FILE *file, CSeg cseg);
118 static int get_seg(BFile file, CSeg cseg);
119 static int skip_line(BFile file);
120 static int skip_string_const(BFile file);
121 static int skip_char_const(BFile file);
122 static int skip_white(BFile file);
123 static int skip_white_and_comment(BFile file);
124 static int write_c_string(FILE *file, STRING value);
125 static int find_user_seg_end(BFile file, CUserSegs userSegs);
126 static int find_func_name(
132 static int find_func_proto(
140 static int trim_opening_comment(
147 static int grab_string_from_file(
156 CSEG_TYPE *csegTypePtr,
165 static int find_ident(BFile file, char *buf, int bufSize);
166 static int find_matching(
173 static BOOL char_is_legal_for_ident(int iChar, BOOL firstChar);
175 static int skip_comment(
178 MAGIC_COMMENT_TYPE *magicCommentTypeOutPtr
180 static int skip_slash_star_comment(
182 MAGIC_COMMENT_TYPE *magicCommentTypeOutPtr
184 static int skip_slash_slash_comment(
186 MAGIC_COMMENT_TYPE *magicCommentTypeOutPtr
188 static int skip_slash_slash_comment_fwd(
190 MAGIC_COMMENT_TYPE *magicCommentTypeOutPtr
192 static int skip_slash_slash_comment_bwd(
194 MAGIC_COMMENT_TYPE *magicCommentTypeOutPtr
197 static MAGIC_COMMENT_TYPE determine_magic_comment_type(STRING cmt);
198 static int get_char_from_c_file(
200 MAGIC_COMMENT_TYPE *magicCommentTypeOutPtr
203 static COMMENT_TYPE find_comment_start(BFile file, long *commentOffOut);
204 static int reverse_string(STRING buf);
205 static int cvt_offset_to_line(BFile file, long offset);
206 static int set_user_seg_next_pointers(CSegArray segArray, BFile file);
207 static int user_seg_construct(CUserSeg userSeg);
208 static BOOL user_seg_is_valid(CUserSeg userSeg);
211 /*************************************************************************
212 *************************************************************************
214 ** Public Entry Points **
216 *************************************************************************
217 *************************************************************************/
220 abmfP_parse_c_file(FILE *cFile, CSegArray *segmentsOutPtr)
222 int return_value = 0;
223 int rc = 0; /* return code */
225 CSegArray segArray = NULL;
228 BFile bfile = &bfileRec;
230 bfile_construct(bfile, cFile);
231 segArray = cseg_array_create();
232 if (segArray == NULL)
234 return_code(ERR_NO_MEMORY);
237 memset(&seg, 0, sizeof(seg));
238 while ((rc = get_seg(bfile, &seg)) >= 0)
244 util_dprintf(1, "Seg: %s lines:%d-%d length:%ld userSegs:%d\n",
245 seg.type == CSEG_GLOBAL? "[GLOBAL]": util_strsafe(seg.name),
246 cvt_offset_to_line(bfile, seg.offset),
247 cvt_offset_to_line(bfile, seg.offset + seg.length
248 + (seg.length==0? 0:-1)),
250 seg.userSegs.numSegs);
252 for (i = 0; i < seg.userSegs.numSegs; ++i)
254 STRING string = NULL;
255 util_dprintf(1, " =>UserSeg: %d-%ld [%ld+%ld bytes]\n",
256 cvt_offset_to_line(bfile, seg.userSegs.segs[i].offset),
257 cvt_offset_to_line(bfile, seg.userSegs.segs[i].offset +
258 + seg.userSegs.segs[i].length
259 + (seg.userSegs.segs[i].length<1? 0:-1)),
260 seg.userSegs.segs[i].offset,
261 seg.userSegs.segs[i].length);
262 grab_string_from_file(&string, bfile,
263 seg.userSegs.segs[i].offset,
264 seg.userSegs.segs[i].length);
265 util_dprintf(1, "|%s|\n", util_strsafe(string));
272 segArray->segs = (CSeg)realloc(
273 segArray->segs, numSegs * sizeof(CSegRec));
274 if (segArray->segs == NULL)
276 cseg_array_destroy(segArray);
277 util_printf_err("Out of memory!\n");
280 segArray->segs[numSegs-1] = seg;
281 memset(&seg, 0, sizeof(seg));
283 segArray->numSegs = numSegs;
285 if ((rc < 0) && (rc != ERR_EOF))
287 /* failure occured */
288 segArray->numSegs = 0;
293 segArray->numSegs = numSegs;
297 * Set up all user segment next pointers
299 set_user_seg_next_pointers(segArray, bfile);
300 return_value = numSegs;
303 *segmentsOutPtr = segArray;
304 bfile_destruct(bfile);
309 /*************************************************************************
311 ** PRIVATE SYMBOLS **
313 *************************************************************************
314 *************************************************************************/
317 set_user_seg_next_pointers(CSegArray segArray, BFile file)
320 CUserSeg curUserSeg = NULL;
321 CUserSeg lastUserSeg = NULL;
323 int userSegCount = 0;
325 for (segCount = 0; segCount < segArray->numSegs; ++segCount)
327 curSeg = &(segArray->segs[segCount]);
328 for (userSegCount = 0; userSegCount < curSeg->userSegs.numSegs;
331 curUserSeg = &(curSeg->userSegs.segs[userSegCount]);
332 if (lastUserSeg == NULL)
334 /* first user segment */
335 segArray->firstUserSeg = curUserSeg;
339 lastUserSeg->next = curUserSeg;
342 curUserSeg->line = -1;
343 curUserSeg->line = cvt_offset_to_line(file, curUserSeg->offset);
344 lastUserSeg = curUserSeg;
353 char_is_legal_for_ident(int iChar, BOOL firstChar)
357 || (firstChar? isalpha(iChar):isalnum(iChar)) );
364 CSEG_TYPE *segTypePtr,
373 int return_value = 0;
376 long openingParenOff = 0;
377 long openingBraceOff = 0;
378 long closingBraceOff = 0;
383 BOOL lookForIdent = TRUE;
384 CSEG_TYPE segType = CSEG_UNDEF;
385 MAGIC_COMMENT_TYPE magicCommentType = MAGIC_CMT_UNDEF;
390 return_code(ERR_EOF);
394 segOff = bfile_get_off(file); /* for global segments */
396 while ((segType == CSEG_UNDEF) && (!bfile_eof(file)))
399 * Scan, looking for opening {
401 openingBraceOff = -1;
402 while ((openingBraceOff < 0) && (!bfile_eof(file)))
404 iChar = get_char_from_c_file(file, &magicCommentType);
411 if (magicCommentType != MAGIC_CMT_UNDEF)
414 * Found user seg in global segment
416 CUserSeg userSeg = NULL;
417 ++(userSegs->numSegs);
418 userSeg = &(userSegs->segs[(userSegs->numSegs)-1]);
419 user_seg_construct(userSeg);
424 userSeg->offset = bfile_get_off(file);
426 if (find_user_seg_end(file, userSegs) < 0)
430 segLen = bfile_get_off(file) - segOff + 1;
433 if (iChar == '{') /* } vi hack */
435 openingBraceOff = (bfile_get_off(file)-1);
436 if (userSegs->numSegs > 0)
438 /* we found global segs before this object */
439 segType = CSEG_GLOBAL;
440 bfile_backup(file, 1);
441 segLen = bfile_get_off(file) - segOff + 1;
445 } /* while openingBraceOff < 0 */
446 if (openingBraceOff < 0)
449 * Global segment, or end of file
451 if (bfile_get_off(file) > segOff)
453 /* found segment at end of file */
454 segType = CSEG_GLOBAL;
456 else if (iChar == EOF)
458 return_value = ERR_EOF;
466 segOff = openingBraceOff;
469 * Look for preceding ')', or ident
471 bfile_set_off(file, openingBraceOff-1);
474 openingParenOff = -1;
479 iChar = get_char_from_c_file(file, NULL);
482 lookForIdent = FALSE;
484 else if (iChar == ';')
486 if (openingParenOff >= 0)
488 lookForIdent = FALSE; /* end of parse */
492 /* if a ; is seen between () and {}, it should be an
493 * old-style parameter list declaration
498 else if (iChar == ')')
500 /* no ident - look for () */
502 if (find_matching(file, '(', &openingParenOff, NULL)
503 /* ) vi hack */ >= 0)
511 "Bad function definition at or near line %d\n",
512 cvt_offset_to_line(file, openingBraceOff-2));
513 lookForIdent = FALSE;
518 else if (iChar == ']')
520 if (find_matching(file, '[', NULL, NULL) >= 0) /* ] vi hack */
522 segType = CSEG_AGGREGATE_VAR;
527 util_printf_err("Unbalanced '[' at or near line %d\n",
528 cvt_offset_to_line(file, bfile_get_off(file)));
530 lookForIdent = FALSE;
537 if (char_is_legal_for_ident(iChar, FALSE))
539 ident[identLen++] = iChar;
541 else if (identLen > 0)
543 /* found end of ident */
544 lookForIdent = FALSE;
549 reverse_string(ident); /* was read backwards */
552 * If it's a function, find the function name
553 * NB: bfile is reversed
557 long off = bfile_get_off(file);
559 if (find_ident(file, ident, 1024) < 0)
561 util_printf_err("Syntax error at or near line %d\n",
562 cvt_offset_to_line(file, off));
567 segOff = identOff = (bfile_get_off(file)+1);
572 * If undef, it should be a type definition.
573 * NB: bfile is reversed
575 if ((identLen > 0) && (segType == CSEG_UNDEF))
578 lookForIdent = FALSE;
580 if ( util_streq(ident, "struct")
581 || util_streq(ident, "union")
582 || util_streq(ident, "enum")
583 || util_streq(ident, "class") )
586 segType = CSEG_AGGREGATE_TYPE;
591 * This could be a variable assignment or an aggregate
592 * type. The ident is the proper name for this one.
594 segType = CSEG_AGGREGATE_TYPE;
596 } /* segType == CSEG_UNDEF */
600 * Get closing brace to find end.
603 bfile_set_off(file, openingBraceOff);
604 bfile_get_char(file); /* skip brace */
606 if (find_matching(file, '}', &closingBraceOff, userSegs) < 0)
608 util_printf_err("Unbalanced '{' at line %d.\n", /* } vi hack */
609 cvt_offset_to_line(file, openingBraceOff));
614 * If name is still undef, it should be an aggregate type, and
615 * the name should follow the closing brace.
619 if ((identLen < 1) && (segType != CSEG_FUNC))
621 if (find_ident(file, ident, 1024) >= 0)
623 segType = CSEG_AGGREGATE_TYPE;
626 } /* while segType */
629 (*segTypePtr) = segType;
630 (*segOffPtr) = segOff;
631 (*segLenPtr) = segLen;
632 (*bodyOffPtr) = openingBraceOff;
633 (*bodyLenPtr) = (closingBraceOff - openingBraceOff) + 1;
634 util_strncpy(namePtr, ident, 1024);
635 if ((segType != CSEG_UNDEF) && (segType != CSEG_GLOBAL))
637 /* {} segment - calculate metrics by braces
639 (*bodyOffPtr) = openingBraceOff;
640 (*bodyLenPtr) = (closingBraceOff - openingBraceOff) + 1;
641 (*segLenPtr) = closingBraceOff - segOff + 1;
644 if ( (return_value >= 0)
645 && ((segType == CSEG_UNDEF) || ((*segOffPtr) < 0) || ((*segLenPtr) < 0))
656 * Finds the end of a user segment.
657 * Assumes: beginning of segment as been read.
658 * Effects: reads past entire segment
661 find_user_seg_end(BFile file, CUserSegs userSegs)
663 int return_value = 0;
664 BOOL segmentIsBad = FALSE;
666 MAGIC_COMMENT_TYPE magicCommentType = MAGIC_CMT_UNDEF;
667 CUserSeg userSeg = &(userSegs->segs[(userSegs->numSegs)-1]);
670 if (userSegs->numSegs < 1)
672 return_code(ERR_CLIENT);
675 segEndOff = bfile_get_off(file)-1;
677 (iChar != EOF) && (magicCommentType == MAGIC_CMT_UNDEF);
678 iChar = get_char_from_c_file(file, &magicCommentType) )
682 segEndOff = file->lastNewlineOff;
686 if (magicCommentType != MAGIC_CMT_USER_END)
697 /* include final newline */
698 userSeg->length = segEndOff - userSeg->offset + 1;
699 if (userSeg->length < 0)
705 if (!user_seg_is_valid(userSeg))
708 --(userSegs->numSegs);
709 return_value = ERR_INTERNAL;
714 util_printf_err("Bad DTB_USER segment, line %d\n",
715 cvt_offset_to_line(file, userSeg->offset));
731 BOOL foundIdent = FALSE;
736 skip_white_and_comment(file);
739 iChar = bfile_get_char(file);
740 if ((iChar == EOF) || (!char_is_legal_for_ident(iChar, FALSE)))
744 else if (bufLen >= (bufSize-1))
750 buf[bufLen++] = iChar;
754 foundIdent = ((*buf) != 0);
756 if (foundIdent && bfile_is_reverse(file))
763 printf("found ident '%s'\n", buf);
766 return foundIdent? 0:-1;
771 reverse_string(STRING buf)
773 int bufLen = strlen(buf);
777 for (i = 0; i < (bufLen/2); ++i)
780 buf[i] = buf[bufLen-1-i];
781 buf[bufLen-1-i] = tempChar;
788 * Gets the next C segment from the file.
791 get_seg(BFile file, CSeg cseg)
793 int return_value = 0;
794 int rc = 0; /* return code */
795 BOOL foundSeg = FALSE;
796 CSEG_TYPE segType = CSEG_UNDEF;
810 CUserSegsRec userSegs;
812 userSegs.numSegs = 0;
813 cseg->type = CSEG_UNDEF;
815 &segType, segName, &segOff, &segLen, &bodyOff, &bodyLen,
817 return_if_err(rc,rc);
820 * Put the info into the func structure
822 cseg->type = segType;
823 cseg->name = strdup(segName);
824 cseg->offset = segOff;
825 cseg->length = segLen;
827 cseg->declaration = NULL;
828 cseg->userSegs = userSegs;
829 for (i = 0; i < cseg->userSegs.numSegs; ++i)
831 grab_string_from_file(&(cseg->userSegs.segs[i].text),
833 cseg->userSegs.segs[i].offset,
834 cseg->userSegs.segs[i].length);
843 grab_string_from_file(
850 #define string (*stringPtr)
859 BFileStateRec fileState;
861 bfile_save_state(file, &fileState);
862 string = (STRING)util_malloc((size_t)(stringLen + 1));
863 bfile_set_off(file, stringOff);
864 fread(string, 1, (size_t)stringLen, file->stream);
865 string[stringLen]= 0;
866 bfile_restore_state(file, &fileState);
875 * userSegs is ignored, if it is NULL
885 int return_value = 0;
889 BOOL foundMatching = FALSE;
891 long startOff = bfile_get_off(file);
892 MAGIC_COMMENT_TYPE magicCommentType = MAGIC_CMT_UNDEF;
894 while ((!quit) && (!bfile_eof(file)))
896 iChar = get_char_from_c_file(file, &magicCommentType);
897 lCharOff = bfile_get_off(file);
900 * Process magic comments
902 if (userSegs != NULL)
904 switch (magicCommentType)
906 case MAGIC_CMT_USER_START:
907 if ( (userSegs->numSegs > 0)
908 && (!user_seg_is_valid(
909 &(userSegs->segs[(userSegs->numSegs)-1]))))
911 /* last segment was not terminated */
912 --(userSegs->numSegs);
916 CUserSeg userSeg = NULL;
922 ++(userSegs->numSegs);
923 userSegs->segs[(userSegs->numSegs)-1].offset
924 = bfile_get_off(file);
925 userSegs->segs[(userSegs->numSegs)-1].length = -1;
926 userSeg = &(userSegs->segs[(userSegs->numSegs)-1]);
927 user_seg_construct(userSeg);
928 userSeg->offset = bfile_get_off(file);
930 if (find_user_seg_end(file, userSegs) < 0)
937 case MAGIC_CMT_USER_END:
939 * This should have been found by find_user_seg_end().
941 util_printf_err("Bad DTB_USER segment at line %d\n",
942 cvt_offset_to_line(file, bfile_get_off(file))-1);
946 } /* userSegs != NULL */
948 if (iChar == matchChar)
951 foundMatching = TRUE;
962 skip_string_const(file);
966 skip_char_const(file);
970 if (find_matching(file, '}', NULL, userSegs) < 0)
972 util_printf_err("Unbalanced '{' at line %d.\n",
973 cvt_offset_to_line(file, lCharOff));
979 if (find_matching(file, '{', NULL, userSegs) < 0)
981 util_printf_err("Unbalanced '}' at line %d.\n",
982 cvt_offset_to_line(file, lCharOff));
988 if (find_matching(file, ')', NULL, userSegs) < 0)
990 util_printf_err("Unbalanced '(' at line %d.\n",
991 cvt_offset_to_line(file, lCharOff));
997 if (find_matching(file, '(', NULL, userSegs) < 0)
999 util_printf_err("Unbalanced ')' at line %d.\n",
1000 cvt_offset_to_line(file, lCharOff));
1004 } /* switch iChar */
1005 } /* ! iChar==matchChar */
1006 } /* while !quit... */
1011 /* printf("<<match found(%c) for %ld>>\n", matchChar, startOff); */
1012 if (matchOffPtr != NULL)
1014 matchOff = bfile_get_off(file) + (file->reverse? 1:-1);
1015 *matchOffPtr = matchOff;
1018 if ((return_value >= 0) && (!foundMatching))
1023 return return_value;
1028 user_seg_construct(CUserSeg userSeg)
1030 memset(userSeg, 0, sizeof(*userSeg));
1031 userSeg->offset = -1;
1032 userSeg->length = -1;
1038 user_seg_is_valid(CUserSeg userSeg)
1040 return ( (userSeg->offset > -1)
1041 && (userSeg->length > -1) );
1046 skip_line(BFile file)
1049 while (((iChar = bfile_get_char(file)) != EOF) && (iChar != '\n'))
1057 * Assumes: opening " has been read
1060 skip_string_const(BFile file)
1063 while (((iChar = bfile_get_char(file)) != EOF)
1069 bfile_get_char(file);
1077 * Assumes: opening ' has been read
1080 skip_char_const(BFile file)
1083 while (((iChar = bfile_get_char(file)) != EOF)
1085 && (iChar != '\'') )
1089 bfile_get_char(file);
1097 skip_white(BFile file)
1099 int iChar = bfile_get_char(file);
1101 while ((iChar != EOF) && (isspace(iChar)))
1103 iChar = bfile_get_char(file);
1107 bfile_backup(file, 1);
1114 skip_white_and_comment(BFile file)
1116 int iChar = get_char_from_c_file(file, NULL);
1118 while ((iChar != EOF) && (isspace(iChar)))
1120 iChar = get_char_from_c_file(file, NULL);
1124 bfile_backup(file, 1);
1131 * Gets a char from a C source file, skipping comments
1134 get_char_from_c_file(
1136 MAGIC_COMMENT_TYPE *magicCommentTypeOutPtr
1142 if (magicCommentTypeOutPtr != NULL)
1144 *magicCommentTypeOutPtr = MAGIC_CMT_UNDEF;
1149 iChar = bfile_get_char(file);
1157 if (bfile_is_forward(file))
1163 if (skip_slash_slash_comment(file, magicCommentTypeOutPtr) < 0)
1172 if (bfile_is_forward(file))
1174 iChar = bfile_get_char(file);
1177 skip_slash_slash_comment(file, magicCommentTypeOutPtr);
1179 else if (iChar == '*')
1181 skip_slash_star_comment(file, magicCommentTypeOutPtr);
1185 bfile_backup(file, 1);
1191 if ((iChar = bfile_get_char(file)) == '*')
1193 skip_slash_star_comment(file, magicCommentTypeOutPtr);
1197 bfile_backup(file, 1);
1215 COMMENT_TYPE commentType,
1216 MAGIC_COMMENT_TYPE *magicCommentTypeOutPtr
1219 int return_value = -1;
1221 if (magicCommentTypeOutPtr != NULL)
1223 *magicCommentTypeOutPtr = MAGIC_CMT_UNDEF;
1228 case COMMENT_SLASH_STAR:
1229 return_value = skip_slash_star_comment(
1230 file, magicCommentTypeOutPtr);
1233 case COMMENT_SLASH_SLASH:
1234 return_value = skip_slash_slash_comment(
1235 file, magicCommentTypeOutPtr);
1239 return return_value;
1244 skip_slash_slash_comment(
1246 MAGIC_COMMENT_TYPE *magicCommentTypeOutPtr
1249 int return_value = -1;
1251 if (bfile_is_forward(file))
1253 return_value = skip_slash_slash_comment_fwd(
1254 file, magicCommentTypeOutPtr);
1258 return_value = skip_slash_slash_comment_bwd(
1259 file, magicCommentTypeOutPtr);
1261 return return_value;
1266 skip_slash_slash_comment_fwd(
1268 MAGIC_COMMENT_TYPE *magicCommentTypeOutPtr
1272 char cmtBuf[MAGIC_COMMENT_MAX_SIZE];
1275 while ((iChar != EOF) && (iChar != '\n'))
1277 iChar = bfile_get_char(file);
1278 if ( ((char_is_legal_for_ident(iChar, FALSE)) || (cmtBufLen > 0))
1279 && (cmtBufLen < MAGIC_COMMENT_MAX_LEN) )
1281 cmtBuf[cmtBufLen++] = iChar;
1284 cmtBuf[cmtBufLen] = 0;
1286 if (magicCommentTypeOutPtr != NULL)
1288 *magicCommentTypeOutPtr = determine_magic_comment_type(cmtBuf);
1295 skip_slash_slash_comment_bwd(
1297 MAGIC_COMMENT_TYPE *magicCommentTypeOutPtr
1300 long startOff = bfile_get_off(file);
1301 BOOL foundCommentStart = FALSE;
1305 if (magicCommentTypeOutPtr != NULL)
1307 *magicCommentTypeOutPtr = MAGIC_CMT_UNDEF;
1311 iChar = bfile_get_char(file);
1320 if ((iChar = bfile_get_char(file)) == '/')
1322 foundCommentStart = TRUE;
1327 bfile_backup(file, 1);
1333 if (!foundCommentStart)
1335 bfile_set_off(file, startOff);
1338 return (foundCommentStart? 0:-1);
1343 skip_slash_star_comment(
1345 MAGIC_COMMENT_TYPE *magicCommentTypeOutPtr
1350 BOOL foundCommentEnd = FALSE;
1351 char cmtBuf[MAGIC_COMMENT_MAX_SIZE];
1356 iChar = bfile_get_char(file);
1364 if ( ((char_is_legal_for_ident(iChar, FALSE)) || (cmtBufLen > 0))
1365 && (cmtBufLen < MAGIC_COMMENT_MAX_LEN) )
1367 cmtBuf[cmtBufLen++] = iChar;
1372 if ((iChar = bfile_get_char(file)) == '/')
1374 foundCommentEnd = TRUE;
1379 bfile_backup(file, 1);
1383 cmtBuf[cmtBufLen] = 0;
1384 if (magicCommentTypeOutPtr != NULL)
1386 *magicCommentTypeOutPtr = determine_magic_comment_type(cmtBuf);
1389 return (foundCommentEnd? 0:-1);
1393 static MAGIC_COMMENT_TYPE
1394 determine_magic_comment_type(STRING cmt)
1396 MAGIC_COMMENT_TYPE magicType = MAGIC_CMT_UNDEF;
1397 static int startLen = -1;
1398 static int endLen = -1;
1402 startLen = strlen(magicCommentUserStart);
1403 endLen = strlen(magicCommentUserEnd);
1406 if (strncmp(cmt, magicCommentUserStart, startLen) == 0)
1408 magicType = MAGIC_CMT_USER_START;
1410 else if (strncmp(cmt, magicCommentUserEnd, endLen) == 0)
1412 magicType = MAGIC_CMT_USER_END;
1419 /*************************************************************************
1423 *************************************************************************/
1424 static BOOL bfileP_set_eof(BFile file);
1427 bfile_construct(BFile file, FILE *stream)
1429 file->stream = NULL;
1430 file->reverse = FALSE;
1431 file->lastNewlineOff = -1;
1432 file->lastNewlineOff2 = -1;
1435 return bfile_set_file(file, stream);
1440 bfile_destruct(BFile file)
1442 return bfile_set_file(file, NULL);
1447 bfile_eof(BFile file)
1454 bfile_is_forward(BFile file)
1456 return (!(file->reverse));
1461 bfile_is_reverse(BFile file)
1463 return file->reverse;
1468 bfile_get_char(BFile file)
1477 iChar = fgetc(file->stream);
1482 if (fseek(file->stream, -1, SEEK_END) == 0)
1484 iChar = fgetc(file->stream);
1499 if (fseek(file->stream, -2, SEEK_CUR) != 0)
1512 file->lastNewlineOff2 = file->lastNewlineOff;
1513 file->lastNewlineOff = (bfile_get_off(file) + (file->reverse? 1:-1));
1521 bfile_backup(BFile file, long numBytes)
1523 int returnValue = 0;
1528 posChange = numBytes;
1532 posChange = -1 * numBytes;
1535 if (fseek(file->stream, posChange, SEEK_CUR) == 0)
1550 bfile_set_file(BFile file, FILE *stream)
1552 file->stream = stream;
1553 file->reverse = FALSE;
1554 bfileP_set_eof(file);
1560 bfile_reverse(BFile file)
1562 file->reverse = TRUE;
1563 bfileP_set_eof(file);
1568 bfile_forward(BFile file)
1570 file->reverse = FALSE;
1571 bfileP_set_eof(file);
1577 bfile_get_off(BFile file)
1589 off = ftell(file->stream);
1594 off = ftell(file->stream);
1602 bfile_set_off(BFile file, long off)
1604 int returnValue = 0;
1605 if (fseek(file->stream, off, SEEK_SET) != 0)
1609 bfileP_set_eof(file);
1615 bfile_save_state(BFile file, BFileState state)
1617 state->forward = bfile_is_forward(file);
1618 state->offset = bfile_get_off(file);
1619 state->lastNewlineOff = file->lastNewlineOff;
1620 state->lastNewlineOff2 = file->lastNewlineOff2;
1626 bfile_restore_state(BFile file, BFileState state)
1628 if (!(state->forward))
1630 bfile_reverse(file);
1634 bfile_forward(file);
1636 bfile_set_off(file, state->offset);
1637 file->lastNewlineOff = state->lastNewlineOff;
1638 file->lastNewlineOff2 = state->lastNewlineOff2;
1644 /******************* PRIVATE METHODS **********************/
1647 bfileP_set_eof(BFile file)
1651 if (file->stream == NULL)
1657 /* DTB_USER_CODE_START */
1658 /* DTB_USER_CODE_END*/
1666 file->eof = (feof(file->stream) || ferror(file->stream));
1669 /* DTB_USER_CODE_START */
1673 /* put some goobies here */
1676 /* DTB_USER_CODE_END*/
1686 CSegArray newArray = (CSegArray)util_malloc(sizeof(CSegArrayRec));
1687 if (newArray != NULL)
1689 memset(newArray, 0, sizeof(CSegArrayRec));
1696 cseg_arrayP_destroy_impl(CSegArray *arrayInOutPtr)
1698 CSegArray array = *arrayInOutPtr;
1704 util_free(array->segs);
1707 *arrayInOutPtr = NULL;
1713 cvt_offset_to_line(BFile file, long offset)
1715 static long lastLineOff = 0;
1716 static int lastLineNum = 1;
1720 BFileStateRec startFileState;
1722 bfile_save_state(file, &startFileState);
1723 bfile_forward(file);
1725 if (offset >= lastLineOff)
1727 curOff = lastLineOff;
1728 lineNum = lastLineNum;
1735 bfile_set_off(file, curOff);
1736 while ((curOff < offset) && ((c = bfile_get_char(file)) != EOF))
1742 lastLineNum = lineNum;
1743 lastLineOff = curOff;
1747 bfile_restore_state(file, &startFileState);
1750 * Return file to original state
1757 * This is here as a test (run this program on this file)
1761 old_style_params(x, y, z)
1766 x = x; y = y; z = z;
1772 /*************************************************************************
1773 *************************************************************************
1775 ** DEBUGGING SUPPORT **
1777 *************************************************************************
1778 *************************************************************************/
1783 /* Internationalization defines */
1784 nl_catd Dtb_project_catd = (nl_catd)-1;
1786 /* Workaround for XPG4 API compatibility */
1787 #if !defined(NL_CAT_LOCALE)
1788 #define NL_CAT_LOCALE 0
1792 main(int argc, char *argv[])
1794 STRING inFilename = NULL;
1795 FILE *inFile = NULL;
1796 CSegArray segs = NULL;
1802 util_init(&argc, &argv);
1806 util_printf_err("Usage %s <filename>\n", util_get_program_name());
1810 inFilename = argv[1];
1811 inFile = util_fopen_locked(inFilename, "r");
1818 numSegs = abmfP_parse_c_file(inFile, &segs);
1821 util_printf_err("Error parsing C file. Aborting\n");
1824 util_printf_err("Segs found in file: %d\n", numSegs);
1830 for (segIndex = 0; segIndex < numSegs; ++segIndex)
1832 cseg = &(segs->segs[segIndex]);
1833 util_dprintf(1, "Seg: %s offset:%ld length:%ld userSegs:%d\n",
1834 cseg->type == CSEG_GLOBAL? "[GLOBAL]": util_strsafe(cseg->name),
1837 cseg->userSegs.numSegs);
1838 if (cseg->text != NULL)
1840 printf("|||%s|||\n", cseg->text);
1843 if (cseg->userSegs.numSegs < 1)
1845 printf("[ No user segments ]\n");
1849 for (usegIndex = 0; usegIndex < cseg->userSegs.numSegs; ++usegIndex)
1851 printf("--- user seg %d [line %ld] ---\n%s---\n",
1853 cseg->userSegs.segs[usegIndex].line,
1854 util_strsafe(cseg->userSegs.segs[usegIndex].text));
1865 * Leave this user segment at the end of the file (this file can be
1866 * used to test itself).
1869 /* DTB_USER_CODE_START */
1876 /* DTB_USER_CODE_END*/