libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

cmTagFile.c 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #include "cmPrefix.h"
  2. #include "cmGlobal.h"
  3. #include "cmRpt.h"
  4. #include "cmErr.h"
  5. #include "cmCtx.h"
  6. #include "cmMem.h"
  7. #include "cmMallocDebug.h"
  8. #include "cmLinkedHeap.h"
  9. #include "cmFile.h"
  10. #include "cmTagFile.h"
  11. cmTfH_t cmTfNullHandle = cmSTATIC_NULL_HANDLE;
  12. typedef struct
  13. {
  14. cmErr_t err;
  15. cmFileH_t fH;
  16. cmLHeapH_t lH;
  17. cmTfTag_t* tagArray;
  18. unsigned tagCnt;
  19. unsigned tagAllocCnt;
  20. } cmTf_t;
  21. cmTf_t* _cmTfHandleToPtr( cmTfH_t h )
  22. {
  23. cmTf_t* p = (cmTf_t*)h.h;
  24. assert( p != NULL );
  25. return p;
  26. }
  27. const cmChar_t* _cmTfFlagsToLabel( unsigned flags )
  28. {
  29. switch(flags)
  30. {
  31. case kFuncProtoTfFl: return "p";
  32. case kFuncDefnTfFl: return "d";
  33. case kEnumTfFl: return "e";
  34. case kMacroTfFl: return "m";
  35. case kTypedefTfFl: return "t";
  36. case kFieldTfFl: return "f";
  37. case kExternTfFl: return "x";
  38. case kStructTagTfFl:return "s";
  39. case kUnionTagTfFl: return "u";
  40. default:
  41. { assert(0); }
  42. }
  43. return "<unknown>";
  44. }
  45. void _cmTfPrintTag(cmRpt_t* rpt, const cmTfTag_t* r )
  46. {
  47. cmRptPrintf(rpt,"%s %5i %s\n",_cmTfFlagsToLabel(r->flags),r->line,r->label);
  48. }
  49. cmTfRC_t _cmTfCloseFile( cmTf_t* p )
  50. {
  51. cmTfRC_t rc = kOkTfRC;
  52. if( cmFileIsValid(p->fH) )
  53. cmFileClose(&p->fH);
  54. if( cmLHeapIsValid(p->lH) )
  55. cmLHeapDestroy(&p->lH);
  56. cmMemFree(p);
  57. return rc;
  58. }
  59. cmTfRC_t _cmTfSyntaxErr( cmTf_t* p, const cmChar_t* fn, unsigned line, const cmChar_t* msg )
  60. {
  61. return cmErrMsg(&p->err,kSyntaxErrTfRC,"Syntax error: %s line:%i in file:%s\n",msg,line,cmStringNullGuard(fn));
  62. }
  63. cmTfRC_t _cmTfParseLine( cmTf_t* p, const cmChar_t* fn, unsigned line, cmChar_t* buf, unsigned bufCharCnt )
  64. {
  65. cmTfRC_t rc = kOkTfRC;
  66. const cmChar_t lineLabel[] = "line:";
  67. unsigned lineLabelCharCnt = strlen(lineLabel);
  68. char* s;
  69. cmTfTag_t r;
  70. memset(&r,0,sizeof(r));
  71. // if the line is empty
  72. if( buf==NULL || bufCharCnt == 0 )
  73. return rc;
  74. // eat leading white space
  75. while( *buf && isspace(*buf) )
  76. ++buf;
  77. // if the line is now empty
  78. if( *buf == 0 )
  79. return rc;
  80. // skip the file header lines - which begin with a '!' character
  81. if( *buf == '!' )
  82. return rc;
  83. // locate the end of the first (tag) field
  84. if( (s= strchr(buf,'\t')) == NULL )
  85. return _cmTfSyntaxErr(p,fn,line,"No tag label was found.");
  86. // zero terminate and copy construct the tag field into r.label
  87. *s = 0;
  88. r.label = cmLhAllocStr( p->lH, buf );
  89. buf = s + 1; // buf now points to the file name
  90. if( (s = strchr(buf,'\t')) == NULL )
  91. return _cmTfSyntaxErr(p,fn,line,"No file name field found.");
  92. buf = s + 1; // buf now points to the 'EX" field
  93. if( (s = strchr(buf,'\t')) == NULL )
  94. return _cmTfSyntaxErr(p,fn,line,"No 'EX' field found.");
  95. buf = s + 1; // buf now points to the 'kind' field
  96. //
  97. // Use: 'ctags --list-kinds=c' to list all of the 'kind' character flags.
  98. //
  99. switch( *buf )
  100. {
  101. case 'd': // macro
  102. r.flags |= kMacroTfFl;
  103. break;
  104. case 'e': // enum value
  105. r.flags |= kEnumTfFl;
  106. break;
  107. case 'p': // function prototype
  108. r.flags |= kFuncProtoTfFl;
  109. break;
  110. case 'f': // function defn
  111. r.flags |= kFuncDefnTfFl;
  112. break;
  113. case 't': // typedef
  114. r.flags |= kTypedefTfFl;
  115. break;
  116. case 'm': // member
  117. r.flags |= kFieldTfFl;
  118. break;
  119. case 'x': // externs and forward decl's
  120. r.flags |= kExternTfFl;
  121. break;
  122. case 's': // struct tag
  123. r.flags |= kStructTagTfFl;
  124. break;
  125. case 'u': // union tag
  126. r.flags |= kUnionTagTfFl;
  127. break;
  128. default: // unrecognized type
  129. return rc;
  130. }
  131. if( (s = strchr(buf,'\t')) == NULL )
  132. return _cmTfSyntaxErr(p,fn,line,"No 'kind' field found.");
  133. buf = s + 1; // buf now points to the 'line' field
  134. //
  135. if( strncmp(buf,lineLabel,lineLabelCharCnt) != 0 )
  136. return _cmTfSyntaxErr(p,fn,line,"No 'line' field found.");
  137. buf += lineLabelCharCnt; // buf now points to the number part of the line field
  138. // parse the line number
  139. if( sscanf(buf,"%i",&r.line) != 1 )
  140. return _cmTfSyntaxErr(p,fn,line,"Line number parse failed.");
  141. // store the tag record
  142. p->tagArray[ p->tagCnt ] = r;
  143. ++p->tagCnt;
  144. return rc;
  145. }
  146. cmTfRC_t cmTfOpenFile( cmCtx_t* ctx, cmTfH_t* hp, const cmChar_t* fn )
  147. {
  148. cmTfRC_t rc = kOkTfRC;
  149. cmTf_t* p = cmMemAllocZ(cmTf_t,1);
  150. cmChar_t* bufPtr = NULL;
  151. unsigned lineCnt = 0;
  152. cmErrSetup(&p->err,&ctx->rpt,"Tag File");
  153. // create the internal linked heap
  154. if( cmLHeapIsValid(p->lH = cmLHeapCreate(8192,ctx)) == false )
  155. {
  156. rc = cmErrMsg(&p->err,kLHeapFailTfRC,"The internal link heap create failed.");
  157. goto errLabel;
  158. }
  159. // open the file
  160. if( cmFileOpen( &p->fH, fn, kReadFileFl, &ctx->rpt ) != kOkFileRC )
  161. {
  162. rc = cmErrMsg(&p->err,kFileFailTfRC,"The tag file '%s' could not be opened.",cmStringNullGuard(fn));
  163. goto errLabel;
  164. }
  165. // get a count of the lines in the file
  166. if( cmFileLineCount( p->fH, &p->tagAllocCnt ) != kOkFileRC || p->tagAllocCnt == 0 )
  167. {
  168. rc = cmErrMsg(&p->err,kFileInvalidTfRC,"The tag file '%s' was invalid or empty.",cmStringNullGuard(fn));
  169. goto errLabel;
  170. }
  171. // allocate the tag array
  172. p->tagArray = cmLhAllocZ(p->lH,cmTfTag_t,p->tagAllocCnt);
  173. while( 1 )
  174. {
  175. unsigned bufByteCnt = 0;
  176. cmFileRC_t frc;
  177. // read a line from the file
  178. if((frc = cmFileGetLineAuto(p->fH, &bufPtr, &bufByteCnt )) != kOkFileRC )
  179. {
  180. if( cmFileEof(p->fH)==false )
  181. rc = cmErrMsg(&p->err,kFileFailTfRC,"File read failed on tag line:%i in '%s'\n",lineCnt+1,cmStringNullGuard(fn));
  182. break;
  183. }
  184. // parse a file line
  185. if((rc = _cmTfParseLine(p,fn,lineCnt+1,bufPtr,bufByteCnt)) != kOkTfRC )
  186. break;
  187. ++lineCnt;
  188. }
  189. cmMemFree(bufPtr);
  190. hp->h = p;
  191. errLabel:
  192. if( rc != kOkTfRC )
  193. _cmTfCloseFile(p);
  194. return rc;
  195. }
  196. cmTfRC_t cmTfCloseFile( cmTfH_t* hp )
  197. {
  198. cmTfRC_t rc = kOkTfRC;
  199. if( hp == NULL || cmTfIsValid(*hp) == false )
  200. return kOkTfRC;
  201. cmTf_t* p = _cmTfHandleToPtr(*hp);
  202. if((rc = _cmTfCloseFile(p)) != kOkTfRC )
  203. return rc;
  204. hp->h = NULL;
  205. return rc;
  206. }
  207. bool cmTfIsValid( cmTfH_t h )
  208. { return h.h != NULL; }
  209. unsigned cmTfCount( cmTfH_t h )
  210. {
  211. cmTf_t* p = _cmTfHandleToPtr(h);
  212. return p->tagCnt;
  213. }
  214. const cmTfTag_t* cmTfRecd( cmTfH_t h, unsigned index )
  215. {
  216. cmTf_t* p = _cmTfHandleToPtr(h);
  217. assert( index < p->tagCnt );
  218. return p->tagArray + index;
  219. }
  220. cmTfRC_t cmTfReport( cmTfH_t h, cmRpt_t* rpt )
  221. {
  222. unsigned i;
  223. cmTf_t* p = _cmTfHandleToPtr(h);
  224. for(i=0; i<p->tagCnt; ++i)
  225. {
  226. cmRptPrintf(rpt,"%5i ",i);
  227. _cmTfPrintTag(rpt, p->tagArray + i );
  228. }
  229. return kOkTfRC;
  230. }
  231. cmTfRC_t cmTfTest( cmCtx_t* ctx, const cmChar_t* fn )
  232. {
  233. cmTfRC_t rc = kOkTfRC;
  234. cmTfH_t h = cmTfNullHandle;
  235. if((rc = cmTfOpenFile(ctx,&h,fn)) == kOkTfRC )
  236. {
  237. cmTfReport(h,&ctx->rpt);
  238. rc = cmTfCloseFile(&h);
  239. }
  240. return rc;
  241. }