libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

cmTagFile.c 6.5KB

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