Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

568 lines
20 KiB

  1. /* SCCSID = %W% %E% */
  2. /*
  3. * Copyright Microsoft Corporation, 1983-1987
  4. *
  5. * This Module contains Proprietary Information of Microsoft
  6. * Corporation and should be treated as Confidential.
  7. */
  8. /****************************************************************
  9. * *
  10. * NEWSTR.C *
  11. * *
  12. * Routines concerning filenames, strings. *
  13. * *
  14. ****************************************************************/
  15. #include <minlit.h> /* Types, constants, macros */
  16. #include <bndtrn.h> /* More of the same */
  17. #include <bndrel.h> /* More of the same */
  18. #include <lnkio.h> /* Linker I/O definitions */
  19. #include <lnkmsg.h> /* Error messages */
  20. #include <extern.h> /* External declarations */
  21. #include <undname.h>
  22. /*
  23. * LOCAL FUNCTION PROTOTYPES
  24. */
  25. LOCAL unsigned short NEAR Find(unsigned char *s1,
  26. unsigned char b,
  27. unsigned short n);
  28. LOCAL void NEAR DelimParts(unsigned char *psb,
  29. unsigned short *pi1,
  30. unsigned short *pi2,
  31. unsigned short *pi3);
  32. /****************************************************************
  33. * *
  34. * Find: *
  35. * *
  36. * This function takes as its arguments a byte pointer s1, and *
  37. * a BYTE b, and a WORD n. It scans at most n bytes of s1 *
  38. * looking for an occurrence of b. If it finds one, it *
  39. * returns its offset from the beginning of s1, and if it does *
  40. * not, it returns the value INIL. *
  41. * *
  42. ****************************************************************/
  43. LOCAL WORD NEAR Find(s1,b,n) /* Find matching byte */
  44. REGISTER BYTE *s1; /* Pointer to a byte string */
  45. BYTE b; /* Search target */
  46. WORD n; /* Length of s1 */
  47. {
  48. REGISTER WORD i; /* Counter */
  49. i = 0; /* Initialize */
  50. #if ECS
  51. if (b < 0x40) /* b cannot be part of ECS */
  52. {
  53. #endif
  54. while(n--) /* While not at end of string */
  55. {
  56. if(*s1++ == b) return(i); /* If match found, return position */
  57. ++i; /* Increment counter */
  58. }
  59. return(INIL); /* No match */
  60. #if ECS
  61. }
  62. #endif
  63. #if ECS || defined(_MBCS)
  64. /* We have to worry about ECS */
  65. while(n--)
  66. {
  67. if(*s1++ == b) return(i);
  68. ++i;
  69. if (IsLeadByte(s1[-1])) /* If we were on a lead byte */
  70. { /* Advance an extra byte */
  71. s1++;
  72. i++;
  73. n--;
  74. }
  75. }
  76. return(INIL); /* No match */
  77. #endif /* ECS */
  78. }
  79. WORD IFind(sb,b)
  80. BYTE *sb; /* Pointer to length-prefixed string */
  81. BYTE b; /* Search target */
  82. {
  83. return(Find(&sb[1],b,B2W(sb[0]))); /* Call Find() to do the work */
  84. }
  85. /****************************************************************
  86. * *
  87. * BreakLine: *
  88. * *
  89. * This function takes as its arguments an SBTYPE, a pointer *
  90. * to a function, and a character used as a delimiter. It *
  91. * It parses the SBTYPE, applying the given function to every *
  92. * substring delimited by the given delimiter. The function *
  93. * does not return a meaningful value. *
  94. * *
  95. ****************************************************************/
  96. void BreakLine(psb,pfunc,sepchar)
  97. BYTE *psb; /* String to parse */
  98. void (*pfunc)(BYTE *);/* Function pointer */
  99. char sepchar; /* Delimiter */
  100. {
  101. SBTYPE substr; /* Substring */
  102. REGISTER WORD ibeg; /* Index variable */
  103. REGISTER WORD ilen; /* Substring length */
  104. ibeg = 1; /* Initialize */
  105. while(ibeg <= B2W(psb[0])) /* While not at end of string */
  106. {
  107. ilen = Find(&psb[ibeg],sepchar,(WORD)(B2W(psb[0]) - ibeg + 1));
  108. /* Get index of sepchar in string */
  109. if(ilen == INIL) ilen = B2W(psb[0]) - ibeg + 1;
  110. /* Len is all that's left if no sep */
  111. memcpy(&substr[1],&psb[ibeg],ilen);
  112. /* Copy substring into substr */
  113. substr[0] = (BYTE) ilen; /* Store the length */
  114. ibeg += ilen + 1; /* Skip over substring and delimiter */
  115. (*pfunc)(substr); /* Call the specified function */
  116. }
  117. }
  118. #pragma check_stack(on)
  119. /****************************************************************
  120. * *
  121. * UpdateFileParts: *
  122. * *
  123. * "Inherit file pieces from a master template and specify *
  124. * missing Update. Inherit four pieces: disk drive, path, *
  125. * file name, extension." *
  126. * *
  127. * Inputs: psbOld pointer to "old sb that specifies *
  128. * pieces of a file name." *
  129. * psbUpdate pointer to "new pieces." *
  130. * *
  131. * Output: psbOld "updated to reflect missing *
  132. * update." *
  133. * *
  134. ****************************************************************/
  135. void UpdateFileParts(psbOld,psbUpdate)
  136. BYTE *psbOld; /* Name to be updated */
  137. BYTE *psbUpdate; /* The update */
  138. {
  139. char oldDrive[_MAX_DRIVE];
  140. char oldDir[_MAX_DIR];
  141. char oldFname[_MAX_FNAME];
  142. char oldExt[_MAX_EXT];
  143. char updDrive[_MAX_DRIVE];
  144. char updDir[_MAX_DIR];
  145. char updFname[_MAX_FNAME];
  146. char updExt[_MAX_EXT];
  147. char *newDrive;
  148. char *newDir;
  149. char *newFname;
  150. char *newExt;
  151. char newPath[_MAX_PATH];
  152. int newPathLen;
  153. psbOld[psbOld[0]+1] = '\0';
  154. _splitpath(&psbOld[1], oldDrive, oldDir, oldFname, oldExt);
  155. psbUpdate[psbUpdate[0]+1] = '\0';
  156. _splitpath(&psbUpdate[1], updDrive, updDir, updFname, updExt);
  157. // Select components of the updated file path
  158. if (updDrive[0] != '\0')
  159. newDrive = updDrive;
  160. else
  161. newDrive = oldDrive;
  162. if ((updDir[0] != '\0') && !(updDir[0] == '/' && updDir[1] == '\0'))
  163. newDir = updDir; /* This above is a fix for bug # 46 */
  164. else
  165. newDir = oldDir;
  166. // If newDir points to UNC name then forget about drive spec
  167. if ((newDir[0] == '\\') && (newDir[1] == '\\'))
  168. newDrive = NULL;
  169. if (updFname[0] != '\0')
  170. newFname = updFname;
  171. else
  172. newFname = oldFname;
  173. if (updExt[0] != '\0')
  174. newExt = updExt;
  175. else
  176. newExt = oldExt;
  177. _makepath(newPath, newDrive, newDir, newFname, newExt);
  178. newPathLen = strlen(newPath);
  179. if (newPathLen > SBLEN - 1)
  180. newPathLen = SBLEN - 1;
  181. memcpy(&psbOld[1], newPath, newPathLen);
  182. psbOld[0] = (BYTE) newPathLen;
  183. if (newPathLen < SBLEN - 1)
  184. psbOld[newPathLen + 1] = '\0';
  185. else
  186. {
  187. psbOld[SBLEN - 1] = '\0';
  188. OutWarn(ER_fntoolong, psbOld + 1);
  189. fflush(stdout);
  190. }
  191. }
  192. #pragma check_stack(off)
  193. #if OVERLAYS OR SYMDEB
  194. /*
  195. * StripDrivePath (sb)
  196. *
  197. * Strip drive and path from a filename.
  198. * Return pointer to new name, minus drive and path (if any).
  199. */
  200. BYTE *StripDrivePath(sb)
  201. BYTE *sb; /* Length-prefixed filename */
  202. {
  203. StripPath(sb); /* Strip path from name */
  204. if (sb[2] != ':') /* If there is no drive */
  205. return(sb); /* return it as is */
  206. sb[2] = (BYTE) ((sb[0]) - 2); /* Adjust length byte, move it */
  207. return(&sb[2]); /* Return minus drive */
  208. }
  209. #endif
  210. /****************************************************************
  211. * *
  212. * SbCompare: *
  213. * *
  214. * Compares two length-prefixed strings. Returns true if they *
  215. * match. *
  216. * *
  217. * NOTE: When comparison is case-insensitive note that letters *
  218. * will match regardless of case, but, in addition, '{' will *
  219. * match '[', '|' will match '\', '}' will match ']', and *
  220. * '~' will match '^'. *
  221. * *
  222. * NOTE: This routine does not know about DBCS. *
  223. * *
  224. ****************************************************************/
  225. WORD SbCompare(ps1,ps2,fncs)
  226. REGISTER BYTE *ps1; /* Pointer to symbol */
  227. REGISTER BYTE *ps2; /* Pointer to symbol */
  228. WORD fncs; /* True if not case-sensitive */
  229. {
  230. WORD length; /* No. of char.s to compare */
  231. if(*ps1 != *ps2) return(FALSE); /* Lengths must match */
  232. length = B2W(*ps1); /* Get length */
  233. if (!fncs) /* If case-sensitive */
  234. { /* Simple string comparison */
  235. while (length && (*++ps1 == *++ps2))
  236. length--;
  237. return(length ? FALSE : TRUE); /* Success iff nothing left */
  238. }
  239. while(length--)
  240. {
  241. if(*++ps1 == *++ps2) continue; /* Bytes match */
  242. if((*ps1 & 0137) != (*ps2 & 0137)) return(FALSE);
  243. }
  244. return(TRUE); /* They match */
  245. }
  246. #if OSEGEXE
  247. /****************************************************************
  248. * *
  249. * SbUcase: *
  250. * *
  251. * Force a length-prefixed string to upper case. *
  252. * Does not check for punctuation characters. *
  253. * *
  254. ****************************************************************/
  255. void SbUcase(sb)
  256. REGISTER BYTE *sb; /* Length-prefixed string */
  257. {
  258. REGISTER int length;
  259. #ifdef _MBCS
  260. sb[B2W(sb[0])+1] = '\0';
  261. _mbsupr (sb + 1);
  262. #else
  263. /* Loop through symbol, changing lower to upper case. */
  264. for(length = B2W(*sb++); length > 0; --length, ++sb)
  265. {
  266. #if ECS
  267. /* If lead byte character, skip two bytes */
  268. if(IsLeadByte(*sb))
  269. {
  270. --length;
  271. ++sb;
  272. continue;
  273. }
  274. #endif
  275. if(*sb >= 'a' && *sb <= 'z')
  276. *sb -= 'a' - 'A';
  277. }
  278. #endif
  279. }
  280. #endif
  281. /*
  282. * SbSuffix:
  283. *
  284. * Tell if one length-prefixed string is a suffix of another.
  285. */
  286. FTYPE SbSuffix(sb,sbSuf,fIgnoreCase)
  287. REGISTER BYTE *sb; /* String */
  288. REGISTER BYTE *sbSuf; /* Suffix */
  289. WORD fIgnoreCase; /* True if case is to be ignored */
  290. {
  291. WORD suflen; /* Suffix length */
  292. /* Get suffix length. If longer than string, return false. */
  293. suflen = B2W(sbSuf[0]);
  294. if(suflen > B2W(sb[0])) return(FALSE);
  295. /*
  296. * Point to end of suffix and end of string. Loop backwards
  297. * until mismatch or end of suffix.
  298. */
  299. sbSuf = &sbSuf[suflen];
  300. sb = &sb[B2W(sb[0])];
  301. while(suflen--)
  302. {
  303. if(!fIgnoreCase)
  304. {
  305. if(*sb-- != *sbSuf--) return(FALSE);
  306. }
  307. else if((*sb-- | 0x20) != (*sbSuf-- | 0x20)) return(FALSE);
  308. }
  309. return((FTYPE) TRUE);
  310. }
  311. #if NEWSYM
  312. #if !defined( M_I386 ) && !defined( _WIN32 )
  313. /*** GetFarSb - copy a far length-prefixed string
  314. *
  315. * Purpose:
  316. * Copy a far length-prefixed string into a near static buffer.
  317. * Terminate with null byte.
  318. * Return a pointer to the the buffer.
  319. *
  320. * Input:
  321. * psb - pointer to the far string
  322. *
  323. * Output:
  324. * Pointer to the near buffer.
  325. *
  326. * Exceptions:
  327. * None.
  328. *
  329. * Notes:
  330. * Don't call this function twice in the row to get two far strings,
  331. * because the second call will overwite the first string.
  332. *
  333. *************************************************************************/
  334. char *GetFarSb(BYTE FAR *lpsb)
  335. {
  336. static BYTE sb[SBLEN+1]; /* 1 extra for the null byte */
  337. sb[0] = lpsb[0];
  338. FMEMCPY((BYTE FAR *) &sb[1], &lpsb[1], B2W(lpsb[0]));
  339. if (sb[0] + 1 < sizeof(sb))
  340. sb[sb[0] + 1] = 0; /* Some routines expect a terminating 0 */
  341. else
  342. sb[SBLEN] = 0;
  343. return(sb);
  344. }
  345. #endif
  346. #endif
  347. /****************************************************************
  348. * *
  349. * ProcObject: *
  350. * *
  351. * This function takes as its argument a pointer to a length- *
  352. * prefixed string containing the name of an object file. It *
  353. * processes that file name. It does not return a meaningful *
  354. * value. *
  355. * *
  356. ****************************************************************/
  357. void ProcObject(psbObj)/* Process object file name */
  358. REGISTER BYTE *psbObj; /* Object file name */
  359. {
  360. SBTYPE sbFile; /* File name */
  361. #if OVERLAYS
  362. FTYPE frparen; /* True if trailing paren found */
  363. FTYPE flparen; /* True if leading paren found */
  364. #endif
  365. #if CMDMSDOS
  366. BYTE sbExt[5];
  367. #endif
  368. #if OVERLAYS
  369. if(psbObj[B2W(psbObj[0])] == ')') /* If trailing parenthesis found */
  370. {
  371. frparen = (FTYPE) TRUE; /* Set flag true */
  372. --psbObj[0]; /* Delete parenthesis */
  373. }
  374. else frparen = FALSE; /* Else set flag false */
  375. if(psbObj[0] && psbObj[1] == '(') /* If leading parenthesis found */
  376. {
  377. flparen = (FTYPE) TRUE; /* Set flag true */
  378. psbObj[1] = (BYTE) (psbObj[0] - 1);/* Delete parenthesis */
  379. ++psbObj;
  380. }
  381. else flparen = FALSE; /* Else set flag false */
  382. #endif
  383. #if CMDMSDOS
  384. PeelFlags(psbObj); /* Process flags, if any */
  385. #if OVERLAYS
  386. if(psbObj[B2W(psbObj[0])] == ')') /* If trailing parenthesis found */
  387. {
  388. if(frparen) Fatal(ER_nstrpar);
  389. /* Cannot nest parentheses */
  390. frparen = (FTYPE) TRUE; /* Set flag true */
  391. --psbObj[0]; /* Delete parenthesis */
  392. }
  393. #endif
  394. #endif
  395. #if OVERLAYS
  396. if(flparen) /* If leading parenthesis */
  397. {
  398. if(fInOverlay) Fatal(ER_nstlpar);
  399. /* Check if in overlay already */
  400. fInOverlay = (FTYPE) TRUE; /* Set flag */
  401. fOverlays = (FTYPE) TRUE; /* Set flag */
  402. }
  403. #endif
  404. if(psbObj[0]) /* If object name length not zero */
  405. {
  406. #if DEBUG /* If debugging on */
  407. fprintf(stderr," Object "); /* Message */
  408. OutSb(stderr,psbObj); /* File name */
  409. NEWLINE(stderr); /* Newline */
  410. #endif /* End debugging code */
  411. #if CMDMSDOS
  412. memcpy(sbFile,sbDotObj,5); /* Put extension in sbFile */
  413. UpdateFileParts(sbFile,psbObj); /* Add extension to name */
  414. #endif
  415. #if CMDXENIX
  416. memcpy(sbFile,psbObj,B2W(psbObj[0]) + 1);
  417. /* Leave name unchanged */
  418. #endif
  419. #if CMDMSDOS
  420. /* If file has extension ".LIB" then save it as a library
  421. * from which all modules will be extracted.
  422. */
  423. sbExt[0] = 4;
  424. memcpy(sbExt+1,&sbFile[B2W(sbFile[0])-3],4);
  425. if (SbCompare(sbExt, sbDotLib, TRUE))
  426. {
  427. if(ifhLibMac >= IFHLIBMAX) Fatal(ER_libmax);
  428. /* Mark name pointer nil so library won't be searched. */
  429. mpifhrhte[ifhLibMac] = RHTENIL;
  430. SaveInput(sbFile,0L,ifhLibMac++,(WORD)(fInOverlay? iovMac: 0));
  431. }
  432. else
  433. #endif
  434. SaveInput(sbFile,0L,(WORD) FHNIL,(WORD)(fInOverlay? iovMac: 0));
  435. /* Save input file name and address */
  436. }
  437. #if OVERLAYS
  438. if(frparen) /* If trailing parenthesis */
  439. {
  440. if(!fInOverlay) Fatal(ER_unmrpar);
  441. /* Check parentheses */
  442. fInOverlay = FALSE; /* No longer specifying overlay */
  443. if(++iovMac > IOVMAX) Fatal(ER_ovlmax);
  444. /* Increment overlay counter */
  445. }
  446. #endif
  447. }
  448. /*
  449. * fPathChr (ch)
  450. *
  451. * Tells whether or not a given character is a path character.
  452. *
  453. */
  454. FTYPE fPathChr(ch)
  455. char ch;
  456. {
  457. #if OSXENIX
  458. if (ch == '/')
  459. #else
  460. if (ch == '/' || ch == '\\')
  461. #endif
  462. return((FTYPE) TRUE);
  463. return(FALSE);
  464. }
  465. /*** UndecorateSb - undecorate name
  466. *
  467. * Purpose:
  468. * Undecorate length prefixed name.
  469. *
  470. * Input:
  471. * sbSrc - length prefixed decorated name
  472. * sbDst - length prefixed undecorated name
  473. * cbDst - size of sbDst
  474. *
  475. * Output:
  476. * If undecoration is successfull the sbDst contains undecorated
  477. * C++ name, else the sbSrc is copied to the sbDst.
  478. *
  479. * Exceptions:
  480. * None.
  481. *
  482. * Notes:
  483. * None.
  484. *
  485. *************************************************************************/
  486. void UndecorateSb(char FAR *sbSrc, char FAR *sbDst, unsigned cbDst)
  487. {
  488. char FAR *pUndecor;
  489. unsigned len;
  490. // Make sure that decorated string is zero-terminated
  491. if (sbSrc[0] < sizeof(SBTYPE))
  492. sbSrc[sbSrc[0] + 1] = '\0';
  493. else
  494. sbSrc[sizeof(SBTYPE) - 1] = '\0';
  495. pUndecor = __unDName(NULL, (pcchar_t) &sbSrc[1], 0, &malloc, &free, 0);
  496. if (pUndecor == NULL)
  497. {
  498. // Undecorator failed
  499. FMEMCPY(sbDst, sbSrc, sbSrc[0] + 1);
  500. }
  501. else
  502. {
  503. // Add length to the undecorated name
  504. len = FSTRLEN(pUndecor);
  505. len = cbDst - 2 >= len ? len : cbDst - 2;
  506. FMEMCPY(&sbDst[1], pUndecor, len);
  507. sbDst[0] = (BYTE) len;
  508. sbDst[len + 1] = '\0';
  509. FFREE(pUndecor);
  510. }
  511. }