parser.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299
  1. /*
  2. * Spec file parser
  3. *
  4. * Copyright 1993 Robert J. Amstadt
  5. * Copyright 1995 Martin von Loewis
  6. * Copyright 1995, 1996, 1997, 2004 Alexandre Julliard
  7. * Copyright 1997 Eric Youngdale
  8. * Copyright 1999 Ulrich Weigand
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation; either
  13. * version 2.1 of the License, or (at your option) any later version.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #include "config.h"
  25. #include <assert.h>
  26. #include <ctype.h>
  27. #include <stdarg.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include "build.h"
  32. int current_line = 0;
  33. static char ParseBuffer[512];
  34. static char TokenBuffer[512];
  35. static char *ParseNext = ParseBuffer;
  36. static FILE *input_file;
  37. static const char *separator_chars;
  38. static const char *comment_chars;
  39. /* valid characters in ordinal names */
  40. static const char valid_ordname_chars[] = "/$:-_@?<>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  41. static const char * const TypeNames[TYPE_NBTYPES] =
  42. {
  43. "variable", /* TYPE_VARIABLE */
  44. "pascal", /* TYPE_PASCAL */
  45. "equate", /* TYPE_ABS */
  46. "stub", /* TYPE_STUB */
  47. "stdcall", /* TYPE_STDCALL */
  48. "cdecl", /* TYPE_CDECL */
  49. "varargs", /* TYPE_VARARGS */
  50. "extern" /* TYPE_EXTERN */
  51. };
  52. static const char * const FlagNames[] =
  53. {
  54. "norelay", /* FLAG_NORELAY */
  55. "noname", /* FLAG_NONAME */
  56. "ret16", /* FLAG_RET16 */
  57. "ret64", /* FLAG_RET64 */
  58. "register", /* FLAG_REGISTER */
  59. "private", /* FLAG_PRIVATE */
  60. "ordinal", /* FLAG_ORDINAL */
  61. "thiscall", /* FLAG_THISCALL */
  62. "fastcall", /* FLAG_FASTCALL */
  63. "syscall", /* FLAG_SYSCALL */
  64. "import", /* FLAG_IMPORT */
  65. NULL
  66. };
  67. static const char * const ArgNames[ARG_MAXARG + 1] =
  68. {
  69. "word", /* ARG_WORD */
  70. "s_word", /* ARG_SWORD */
  71. "segptr", /* ARG_SEGPTR */
  72. "segstr", /* ARG_SEGSTR */
  73. "long", /* ARG_LONG */
  74. "ptr", /* ARG_PTR */
  75. "str", /* ARG_STR */
  76. "wstr", /* ARG_WSTR */
  77. "int64", /* ARG_INT64 */
  78. "int128", /* ARG_INT128 */
  79. "float", /* ARG_FLOAT */
  80. "double" /* ARG_DOUBLE */
  81. };
  82. static int IsNumberString(const char *s)
  83. {
  84. while (*s) if (!isdigit(*s++)) return 0;
  85. return 1;
  86. }
  87. static inline int is_token_separator( char ch )
  88. {
  89. return strchr( separator_chars, ch ) != NULL;
  90. }
  91. static inline int is_token_comment( char ch )
  92. {
  93. return strchr( comment_chars, ch ) != NULL;
  94. }
  95. /* get the next line from the input file, or return 0 if at eof */
  96. static int get_next_line(void)
  97. {
  98. ParseNext = ParseBuffer;
  99. current_line++;
  100. return (fgets(ParseBuffer, sizeof(ParseBuffer), input_file) != NULL);
  101. }
  102. static const char * GetToken( int allow_eol )
  103. {
  104. char *p;
  105. char *token = TokenBuffer;
  106. for (;;)
  107. {
  108. /* remove initial white space */
  109. p = ParseNext;
  110. while (isspace(*p)) p++;
  111. if (*p == '\\' && p[1] == '\n') /* line continuation */
  112. {
  113. if (!get_next_line())
  114. {
  115. if (!allow_eol) error( "Unexpected end of file\n" );
  116. return NULL;
  117. }
  118. }
  119. else break;
  120. }
  121. if ((*p == '\0') || is_token_comment(*p))
  122. {
  123. if (!allow_eol) error( "Declaration not terminated properly\n" );
  124. return NULL;
  125. }
  126. /*
  127. * Find end of token.
  128. */
  129. if (is_token_separator(*p))
  130. {
  131. /* a separator is always a complete token */
  132. *token++ = *p++;
  133. }
  134. else while (*p != '\0' && !is_token_separator(*p) && !isspace(*p))
  135. {
  136. if (*p == '\\') p++;
  137. if (*p) *token++ = *p++;
  138. }
  139. *token = '\0';
  140. ParseNext = p;
  141. return TokenBuffer;
  142. }
  143. static ORDDEF *add_entry_point( DLLSPEC *spec )
  144. {
  145. ORDDEF *ret;
  146. if (spec->nb_entry_points == spec->alloc_entry_points)
  147. {
  148. spec->alloc_entry_points += 128;
  149. spec->entry_points = xrealloc( spec->entry_points,
  150. spec->alloc_entry_points * sizeof(*spec->entry_points) );
  151. }
  152. ret = &spec->entry_points[spec->nb_entry_points++];
  153. memset( ret, 0, sizeof(*ret) );
  154. return ret;
  155. }
  156. /*******************************************************************
  157. * parse_spec_variable
  158. *
  159. * Parse a variable definition in a .spec file.
  160. */
  161. static int parse_spec_variable( ORDDEF *odp, DLLSPEC *spec )
  162. {
  163. char *endptr;
  164. unsigned int *value_array;
  165. int n_values;
  166. int value_array_size;
  167. const char *token;
  168. if (spec->type == SPEC_WIN32)
  169. {
  170. error( "'variable' not supported in Win32, use 'extern' instead\n" );
  171. return 0;
  172. }
  173. if (!(token = GetToken(0))) return 0;
  174. if (*token != '(')
  175. {
  176. error( "Expected '(' got '%s'\n", token );
  177. return 0;
  178. }
  179. n_values = 0;
  180. value_array_size = 25;
  181. value_array = xmalloc(sizeof(*value_array) * value_array_size);
  182. for (;;)
  183. {
  184. if (!(token = GetToken(0)))
  185. {
  186. free( value_array );
  187. return 0;
  188. }
  189. if (*token == ')')
  190. break;
  191. value_array[n_values++] = strtoul(token, &endptr, 0);
  192. if (n_values == value_array_size)
  193. {
  194. value_array_size += 25;
  195. value_array = xrealloc(value_array,
  196. sizeof(*value_array) * value_array_size);
  197. }
  198. if (endptr == NULL || *endptr != '\0')
  199. {
  200. error( "Expected number value, got '%s'\n", token );
  201. free( value_array );
  202. return 0;
  203. }
  204. }
  205. odp->u.var.n_values = n_values;
  206. odp->u.var.values = xrealloc(value_array, sizeof(*value_array) * n_values);
  207. return 1;
  208. }
  209. /*******************************************************************
  210. * parse_spec_arguments
  211. *
  212. * Parse the arguments of an entry point.
  213. */
  214. static int parse_spec_arguments( ORDDEF *odp, DLLSPEC *spec, int optional )
  215. {
  216. const char *token;
  217. unsigned int i, arg;
  218. int is_win32 = (spec->type == SPEC_WIN32) || (odp->flags & FLAG_EXPORT32);
  219. if (!(token = GetToken( optional ))) return optional;
  220. if (*token != '(')
  221. {
  222. error( "Expected '(' got '%s'\n", token );
  223. return 0;
  224. }
  225. odp->u.func.nb_args = 0;
  226. for (i = 0; i < MAX_ARGUMENTS; i++)
  227. {
  228. if (!(token = GetToken(0))) return 0;
  229. if (*token == ')')
  230. break;
  231. for (arg = 0; arg <= ARG_MAXARG; arg++)
  232. if (!strcmp( ArgNames[arg], token )) break;
  233. if (arg > ARG_MAXARG)
  234. {
  235. error( "Unknown argument type '%s'\n", token );
  236. return 0;
  237. }
  238. if (is_win32) switch (arg)
  239. {
  240. case ARG_WORD:
  241. case ARG_SWORD:
  242. case ARG_SEGPTR:
  243. case ARG_SEGSTR:
  244. error( "Argument type '%s' only allowed for Win16\n", token );
  245. return 0;
  246. }
  247. odp->u.func.args[i] = arg;
  248. }
  249. if (*token != ')')
  250. {
  251. error( "Too many arguments\n" );
  252. return 0;
  253. }
  254. odp->u.func.nb_args = i;
  255. if (odp->flags & FLAG_THISCALL)
  256. {
  257. if (odp->type != TYPE_STDCALL)
  258. {
  259. error( "A thiscall function must use the stdcall convention\n" );
  260. return 0;
  261. }
  262. if (!i || odp->u.func.args[0] != ARG_PTR)
  263. {
  264. error( "First argument of a thiscall function must be a pointer\n" );
  265. return 0;
  266. }
  267. }
  268. if (odp->flags & FLAG_FASTCALL)
  269. {
  270. if (odp->type != TYPE_STDCALL)
  271. {
  272. error( "A fastcall function must use the stdcall convention\n" );
  273. return 0;
  274. }
  275. if (!i || (odp->u.func.args[0] != ARG_PTR && odp->u.func.args[0] != ARG_LONG))
  276. {
  277. error( "First argument of a fastcall function must be a pointer or integer\n" );
  278. return 0;
  279. }
  280. if (i > 1 && odp->u.func.args[1] != ARG_PTR && odp->u.func.args[1] != ARG_LONG)
  281. {
  282. error( "Second argument of a fastcall function must be a pointer or integer\n" );
  283. return 0;
  284. }
  285. }
  286. if (odp->flags & FLAG_SYSCALL)
  287. {
  288. if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL)
  289. {
  290. error( "A syscall function must use either the stdcall or the cdecl convention\n" );
  291. return 0;
  292. }
  293. }
  294. return 1;
  295. }
  296. /*******************************************************************
  297. * parse_spec_export
  298. *
  299. * Parse an exported function definition in a .spec file.
  300. */
  301. static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
  302. {
  303. const char *token;
  304. int is_win32 = (spec->type == SPEC_WIN32) || (odp->flags & FLAG_EXPORT32);
  305. if (!is_win32 && odp->type == TYPE_STDCALL)
  306. {
  307. error( "'stdcall' not supported for Win16\n" );
  308. return 0;
  309. }
  310. if (is_win32 && odp->type == TYPE_PASCAL)
  311. {
  312. error( "'pascal' not supported for Win32\n" );
  313. return 0;
  314. }
  315. if (!parse_spec_arguments( odp, spec, 0 )) return 0;
  316. if (odp->type == TYPE_VARARGS)
  317. odp->flags |= FLAG_NORELAY; /* no relay debug possible for varags entry point */
  318. if (target.cpu != CPU_i386)
  319. odp->flags &= ~(FLAG_THISCALL | FLAG_FASTCALL);
  320. if (!(token = GetToken(1)))
  321. {
  322. if (!strcmp( odp->name, "@" ))
  323. {
  324. error( "Missing handler name for anonymous function\n" );
  325. return 0;
  326. }
  327. odp->link_name = xstrdup( odp->name );
  328. }
  329. else
  330. {
  331. odp->link_name = xstrdup( token );
  332. if (strchr( odp->link_name, '.' ))
  333. {
  334. if (!is_win32)
  335. {
  336. error( "Forwarded functions not supported for Win16\n" );
  337. return 0;
  338. }
  339. odp->flags |= FLAG_FORWARD;
  340. }
  341. }
  342. return 1;
  343. }
  344. /*******************************************************************
  345. * parse_spec_equate
  346. *
  347. * Parse an 'equate' definition in a .spec file.
  348. */
  349. static int parse_spec_equate( ORDDEF *odp, DLLSPEC *spec )
  350. {
  351. char *endptr;
  352. int value;
  353. const char *token;
  354. if (spec->type == SPEC_WIN32)
  355. {
  356. error( "'equate' not supported for Win32\n" );
  357. return 0;
  358. }
  359. if (!(token = GetToken(0))) return 0;
  360. value = strtol(token, &endptr, 0);
  361. if (endptr == NULL || *endptr != '\0')
  362. {
  363. error( "Expected number value, got '%s'\n", token );
  364. return 0;
  365. }
  366. if (value < -0x8000 || value > 0xffff)
  367. {
  368. error( "Value %d for absolute symbol doesn't fit in 16 bits\n", value );
  369. value = 0;
  370. }
  371. odp->u.abs.value = value;
  372. return 1;
  373. }
  374. /*******************************************************************
  375. * parse_spec_stub
  376. *
  377. * Parse a 'stub' definition in a .spec file
  378. */
  379. static int parse_spec_stub( ORDDEF *odp, DLLSPEC *spec )
  380. {
  381. odp->u.func.nb_args = -1;
  382. odp->link_name = xstrdup("");
  383. return parse_spec_arguments( odp, spec, 1 );
  384. }
  385. /*******************************************************************
  386. * parse_spec_extern
  387. *
  388. * Parse an 'extern' definition in a .spec file.
  389. */
  390. static int parse_spec_extern( ORDDEF *odp, DLLSPEC *spec )
  391. {
  392. const char *token;
  393. if (spec->type == SPEC_WIN16)
  394. {
  395. error( "'extern' not supported for Win16, use 'variable' instead\n" );
  396. return 0;
  397. }
  398. if (!(token = GetToken(1)))
  399. {
  400. if (!strcmp( odp->name, "@" ))
  401. {
  402. error( "Missing handler name for anonymous extern\n" );
  403. return 0;
  404. }
  405. odp->link_name = xstrdup( odp->name );
  406. }
  407. else
  408. {
  409. odp->link_name = xstrdup( token );
  410. if (strchr( odp->link_name, '.' )) odp->flags |= FLAG_FORWARD;
  411. }
  412. return 1;
  413. }
  414. /*******************************************************************
  415. * parse_spec_flags
  416. *
  417. * Parse the optional flags for an entry point in a .spec file.
  418. */
  419. static const char *parse_spec_flags( DLLSPEC *spec, ORDDEF *odp, const char *token )
  420. {
  421. unsigned int i, cpu_mask = 0;
  422. do
  423. {
  424. token++;
  425. if (!strncmp( token, "arch=", 5))
  426. {
  427. char *args = xstrdup( token + 5 );
  428. char *cpu_name = strtok( args, "," );
  429. while (cpu_name)
  430. {
  431. if (!strcmp( cpu_name, "win32" ))
  432. {
  433. if (spec->type == SPEC_WIN32)
  434. odp->flags |= FLAG_CPU_WIN32;
  435. else
  436. odp->flags |= FLAG_EXPORT32;
  437. }
  438. else if (!strcmp( cpu_name, "win64" ))
  439. odp->flags |= FLAG_CPU_WIN64;
  440. else
  441. {
  442. int cpu = get_cpu_from_name( cpu_name + (cpu_name[0] == '!') );
  443. if (cpu == -1)
  444. {
  445. error( "Unknown architecture '%s'\n", cpu_name );
  446. return NULL;
  447. }
  448. if (cpu_name[0] == '!') cpu_mask |= FLAG_CPU( cpu );
  449. else odp->flags |= FLAG_CPU( cpu );
  450. }
  451. cpu_name = strtok( NULL, "," );
  452. }
  453. free( args );
  454. }
  455. else if (!strcmp( token, "i386" )) /* backwards compatibility */
  456. {
  457. odp->flags |= FLAG_CPU(CPU_i386);
  458. }
  459. else
  460. {
  461. for (i = 0; FlagNames[i]; i++)
  462. if (!strcmp( FlagNames[i], token )) break;
  463. if (!FlagNames[i])
  464. {
  465. error( "Unknown flag '%s'\n", token );
  466. return NULL;
  467. }
  468. switch (1 << i)
  469. {
  470. case FLAG_RET16:
  471. case FLAG_REGISTER:
  472. if (spec->type == SPEC_WIN32)
  473. error( "Flag '%s' is not supported in Win32\n", FlagNames[i] );
  474. break;
  475. case FLAG_RET64:
  476. case FLAG_THISCALL:
  477. case FLAG_FASTCALL:
  478. if (spec->type == SPEC_WIN16)
  479. error( "Flag '%s' is not supported in Win16\n", FlagNames[i] );
  480. break;
  481. }
  482. odp->flags |= 1 << i;
  483. }
  484. token = GetToken(0);
  485. } while (token && *token == '-');
  486. if (cpu_mask) odp->flags |= FLAG_CPU_MASK & ~cpu_mask;
  487. return token;
  488. }
  489. /*******************************************************************
  490. * parse_spec_ordinal
  491. *
  492. * Parse an ordinal definition in a .spec file.
  493. */
  494. static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
  495. {
  496. const char *token;
  497. size_t len;
  498. ORDDEF *odp = add_entry_point( spec );
  499. if (!(token = GetToken(0))) goto error;
  500. for (odp->type = 0; odp->type < TYPE_NBTYPES; odp->type++)
  501. if (TypeNames[odp->type] && !strcmp( token, TypeNames[odp->type] ))
  502. break;
  503. if (odp->type >= TYPE_NBTYPES)
  504. {
  505. if (!strcmp( token, "thiscall" )) /* for backwards compatibility */
  506. {
  507. odp->type = TYPE_STDCALL;
  508. odp->flags |= FLAG_THISCALL;
  509. }
  510. else
  511. {
  512. error( "Expected type after ordinal, found '%s' instead\n", token );
  513. goto error;
  514. }
  515. }
  516. if (!(token = GetToken(0))) goto error;
  517. if (*token == '-' && !(token = parse_spec_flags( spec, odp, token ))) goto error;
  518. if (ordinal == -1 && spec->type != SPEC_WIN32 && !(odp->flags & FLAG_EXPORT32))
  519. {
  520. error( "'@' ordinals not supported for Win16\n" );
  521. goto error;
  522. }
  523. odp->name = xstrdup( token );
  524. odp->lineno = current_line;
  525. odp->ordinal = ordinal;
  526. len = strspn( odp->name, valid_ordname_chars );
  527. if (len < strlen( odp->name ))
  528. {
  529. error( "Character '%c' is not allowed in exported name '%s'\n", odp->name[len], odp->name );
  530. goto error;
  531. }
  532. switch(odp->type)
  533. {
  534. case TYPE_VARIABLE:
  535. if (!parse_spec_variable( odp, spec )) goto error;
  536. break;
  537. case TYPE_PASCAL:
  538. case TYPE_STDCALL:
  539. case TYPE_VARARGS:
  540. case TYPE_CDECL:
  541. if (!parse_spec_export( odp, spec )) goto error;
  542. break;
  543. case TYPE_ABS:
  544. if (!parse_spec_equate( odp, spec )) goto error;
  545. break;
  546. case TYPE_STUB:
  547. if (!parse_spec_stub( odp, spec )) goto error;
  548. break;
  549. case TYPE_EXTERN:
  550. if (!parse_spec_extern( odp, spec )) goto error;
  551. break;
  552. default:
  553. assert( 0 );
  554. }
  555. if ((odp->flags & FLAG_CPU_MASK) && !(odp->flags & FLAG_CPU(target.cpu)))
  556. {
  557. /* ignore this entry point */
  558. spec->nb_entry_points--;
  559. return 1;
  560. }
  561. if (data_only && !(odp->flags & FLAG_FORWARD))
  562. {
  563. error( "Only forwarded entry points are allowed in data-only mode\n" );
  564. goto error;
  565. }
  566. if (ordinal != -1)
  567. {
  568. if (!ordinal)
  569. {
  570. error( "Ordinal 0 is not valid\n" );
  571. goto error;
  572. }
  573. if (ordinal >= MAX_ORDINALS)
  574. {
  575. error( "Ordinal number %d too large\n", ordinal );
  576. goto error;
  577. }
  578. if (ordinal > spec->limit) spec->limit = ordinal;
  579. if (ordinal < spec->base) spec->base = ordinal;
  580. odp->ordinal = ordinal;
  581. }
  582. if (odp->type == TYPE_STDCALL && !(odp->flags & FLAG_PRIVATE))
  583. {
  584. if (!strcmp( odp->name, "DllRegisterServer" ) ||
  585. !strcmp( odp->name, "DllUnregisterServer" ) ||
  586. !strcmp( odp->name, "DllMain" ) ||
  587. !strcmp( odp->name, "DllGetClassObject" ) ||
  588. !strcmp( odp->name, "DllGetVersion" ) ||
  589. !strcmp( odp->name, "DllInstall" ) ||
  590. !strcmp( odp->name, "DllCanUnloadNow" ))
  591. {
  592. warning( "Function %s should be marked private\n", odp->name );
  593. if (strcmp( odp->name, odp->link_name ))
  594. warning( "Function %s should not use a different internal name (%s)\n",
  595. odp->name, odp->link_name );
  596. }
  597. }
  598. if (!strcmp( odp->name, "@" ) || odp->flags & (FLAG_NONAME | FLAG_ORDINAL))
  599. {
  600. if (ordinal == -1)
  601. {
  602. if (!strcmp( odp->name, "@" ))
  603. error( "Nameless function needs an explicit ordinal number\n" );
  604. else
  605. error( "Function imported by ordinal needs an explicit ordinal number\n" );
  606. goto error;
  607. }
  608. if (spec->type != SPEC_WIN32)
  609. {
  610. error( "Nameless functions not supported for Win16\n" );
  611. goto error;
  612. }
  613. if (!strcmp( odp->name, "@" ))
  614. {
  615. free( odp->name );
  616. odp->name = NULL;
  617. }
  618. else if (!(odp->flags & FLAG_ORDINAL)) /* -ordinal only affects the import library */
  619. {
  620. odp->export_name = odp->name;
  621. odp->name = NULL;
  622. }
  623. }
  624. return 1;
  625. error:
  626. spec->nb_entry_points--;
  627. free( odp->name );
  628. return 0;
  629. }
  630. static unsigned int apiset_hash_len( const char *str )
  631. {
  632. return strrchr( str, '-' ) - str;
  633. }
  634. static unsigned int apiset_hash( const char *str )
  635. {
  636. unsigned int ret = 0, len = apiset_hash_len( str );
  637. while (len--) ret = ret * apiset_hash_factor + *str++;
  638. return ret;
  639. }
  640. static unsigned int apiset_add_str( struct apiset *apiset, const char *str, unsigned int len )
  641. {
  642. char *ret;
  643. if (!apiset->strings || !(ret = strstr( apiset->strings, str )))
  644. {
  645. if (apiset->str_pos + len >= apiset->str_size)
  646. {
  647. apiset->str_size = max( apiset->str_size * 2, 1024 );
  648. apiset->strings = xrealloc( apiset->strings, apiset->str_size );
  649. }
  650. ret = apiset->strings + apiset->str_pos;
  651. memcpy( ret, str, len );
  652. ret[len] = 0;
  653. apiset->str_pos += len;
  654. }
  655. return ret - apiset->strings;
  656. }
  657. static void add_apiset( struct apiset *apiset, const char *api )
  658. {
  659. struct apiset_entry *entry;
  660. if (apiset->count == apiset->size)
  661. {
  662. apiset->size = max( apiset->size * 2, 64 );
  663. apiset->entries = xrealloc( apiset->entries, apiset->size * sizeof(*apiset->entries) );
  664. }
  665. entry = &apiset->entries[apiset->count++];
  666. entry->name_len = strlen( api );
  667. entry->name_off = apiset_add_str( apiset, api, entry->name_len );
  668. entry->hash = apiset_hash( api );
  669. entry->hash_len = apiset_hash_len( api );
  670. entry->val_count = 0;
  671. }
  672. static void add_apiset_value( struct apiset *apiset, const char *value )
  673. {
  674. struct apiset_entry *entry = &apiset->entries[apiset->count - 1];
  675. if (entry->val_count < ARRAY_SIZE(entry->values) - 1)
  676. {
  677. struct apiset_value *val = &entry->values[entry->val_count++];
  678. char *sep = strchr( value, ':' );
  679. if (sep)
  680. {
  681. val->name_len = sep - value;
  682. val->name_off = apiset_add_str( apiset, value, val->name_len );
  683. val->val_len = strlen( sep + 1 );
  684. val->val_off = apiset_add_str( apiset, sep + 1, val->val_len );
  685. }
  686. else
  687. {
  688. val->name_len = val->name_off = 0;
  689. val->val_len = strlen( value );
  690. val->val_off = apiset_add_str( apiset, value, val->val_len );
  691. }
  692. }
  693. else error( "Too many values for api '%.*s'\n", entry->name_len, apiset->strings + entry->name_off );
  694. }
  695. /*******************************************************************
  696. * parse_spec_apiset
  697. */
  698. static int parse_spec_apiset( DLLSPEC *spec )
  699. {
  700. struct apiset_entry *entry;
  701. const char *token;
  702. unsigned int i, hash;
  703. if (!data_only)
  704. {
  705. error( "Apiset definitions are only allowed in data-only mode\n" );
  706. return 0;
  707. }
  708. if (!(token = GetToken(0))) return 0;
  709. if (!strncmp( token, "api-", 4 ) && !strncmp( token, "ext-", 4 ))
  710. {
  711. error( "Unrecognized API set name '%s'\n", token );
  712. return 0;
  713. }
  714. hash = apiset_hash( token );
  715. for (i = 0, entry = spec->apiset.entries; i < spec->apiset.count; i++, entry++)
  716. {
  717. if (entry->name_len == strlen( token ) &&
  718. !strncmp( spec->apiset.strings + entry->name_off, token, entry->name_len ))
  719. {
  720. error( "Duplicate API set '%s'\n", token );
  721. return 0;
  722. }
  723. if (entry->hash == hash)
  724. {
  725. error( "Duplicate hash code '%.*s' and '%s'\n",
  726. entry->name_len, spec->apiset.strings + entry->name_off, token );
  727. return 0;
  728. }
  729. }
  730. add_apiset( &spec->apiset, token );
  731. if (!(token = GetToken(0)) || strcmp( token, "=" ))
  732. {
  733. error( "Syntax error near '%s'\n", token );
  734. return 0;
  735. }
  736. while ((token = GetToken(1))) add_apiset_value( &spec->apiset, token );
  737. return 1;
  738. }
  739. static int name_compare( const void *ptr1, const void *ptr2 )
  740. {
  741. const ORDDEF *odp1 = *(const ORDDEF * const *)ptr1;
  742. const ORDDEF *odp2 = *(const ORDDEF * const *)ptr2;
  743. const char *name1 = odp1->name ? odp1->name : odp1->export_name;
  744. const char *name2 = odp2->name ? odp2->name : odp2->export_name;
  745. return strcmp( name1, name2 );
  746. }
  747. /*******************************************************************
  748. * assign_names
  749. *
  750. * Build the name array and catch duplicates.
  751. */
  752. static void assign_names( DLLSPEC *spec )
  753. {
  754. int i, j, nb_exp_names = 0;
  755. ORDDEF **all_names;
  756. spec->nb_names = 0;
  757. for (i = 0; i < spec->nb_entry_points; i++)
  758. if (spec->entry_points[i].name) spec->nb_names++;
  759. else if (spec->entry_points[i].export_name) nb_exp_names++;
  760. if (!spec->nb_names && !nb_exp_names) return;
  761. /* check for duplicates */
  762. all_names = xmalloc( (spec->nb_names + nb_exp_names) * sizeof(all_names[0]) );
  763. for (i = j = 0; i < spec->nb_entry_points; i++)
  764. if (spec->entry_points[i].name || spec->entry_points[i].export_name)
  765. all_names[j++] = &spec->entry_points[i];
  766. qsort( all_names, j, sizeof(all_names[0]), name_compare );
  767. for (i = 0; i < j - 1; i++)
  768. {
  769. const char *name1 = all_names[i]->name ? all_names[i]->name : all_names[i]->export_name;
  770. const char *name2 = all_names[i+1]->name ? all_names[i+1]->name : all_names[i+1]->export_name;
  771. if (!strcmp( name1, name2 ) &&
  772. !((all_names[i]->flags ^ all_names[i+1]->flags) & FLAG_EXPORT32))
  773. {
  774. current_line = max( all_names[i]->lineno, all_names[i+1]->lineno );
  775. error( "'%s' redefined\n%s:%d: First defined here\n",
  776. name1, input_file_name,
  777. min( all_names[i]->lineno, all_names[i+1]->lineno ) );
  778. }
  779. }
  780. free( all_names );
  781. if (spec->nb_names)
  782. {
  783. spec->names = xmalloc( spec->nb_names * sizeof(spec->names[0]) );
  784. for (i = j = 0; i < spec->nb_entry_points; i++)
  785. if (spec->entry_points[i].name) spec->names[j++] = &spec->entry_points[i];
  786. /* sort the list of names */
  787. qsort( spec->names, spec->nb_names, sizeof(spec->names[0]), name_compare );
  788. for (i = 0; i < spec->nb_names; i++) spec->names[i]->hint = i;
  789. }
  790. }
  791. /*******************************************************************
  792. * assign_ordinals
  793. *
  794. * Build the ordinal array.
  795. */
  796. static void assign_ordinals( DLLSPEC *spec )
  797. {
  798. int i, count, ordinal;
  799. /* start assigning from base, or from 1 if no ordinal defined yet */
  800. spec->base = MAX_ORDINALS;
  801. spec->limit = 0;
  802. for (i = 0; i < spec->nb_entry_points; i++)
  803. {
  804. ordinal = spec->entry_points[i].ordinal;
  805. if (ordinal == -1) continue;
  806. if (ordinal > spec->limit) spec->limit = ordinal;
  807. if (ordinal < spec->base) spec->base = ordinal;
  808. }
  809. if (spec->base == MAX_ORDINALS) spec->base = 1;
  810. if (spec->limit < spec->base) spec->limit = spec->base;
  811. count = max( spec->limit + 1, spec->base + spec->nb_entry_points );
  812. spec->ordinals = xmalloc( count * sizeof(spec->ordinals[0]) );
  813. memset( spec->ordinals, 0, count * sizeof(spec->ordinals[0]) );
  814. /* fill in all explicitly specified ordinals */
  815. for (i = 0; i < spec->nb_entry_points; i++)
  816. {
  817. ordinal = spec->entry_points[i].ordinal;
  818. if (ordinal == -1) continue;
  819. if (spec->ordinals[ordinal])
  820. {
  821. current_line = max( spec->entry_points[i].lineno, spec->ordinals[ordinal]->lineno );
  822. error( "ordinal %d redefined\n%s:%d: First defined here\n",
  823. ordinal, input_file_name,
  824. min( spec->entry_points[i].lineno, spec->ordinals[ordinal]->lineno ) );
  825. }
  826. else spec->ordinals[ordinal] = &spec->entry_points[i];
  827. }
  828. /* now assign ordinals to the rest */
  829. for (i = 0, ordinal = spec->base; i < spec->nb_entry_points; i++)
  830. {
  831. if (spec->entry_points[i].ordinal != -1) continue;
  832. while (spec->ordinals[ordinal]) ordinal++;
  833. if (ordinal >= MAX_ORDINALS)
  834. {
  835. current_line = spec->entry_points[i].lineno;
  836. fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS );
  837. }
  838. spec->entry_points[i].ordinal = ordinal;
  839. spec->ordinals[ordinal] = &spec->entry_points[i];
  840. }
  841. if (ordinal > spec->limit) spec->limit = ordinal;
  842. }
  843. /*******************************************************************
  844. * add_16bit_exports
  845. *
  846. * Add the necessary exports to the 32-bit counterpart of a 16-bit module.
  847. */
  848. void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 )
  849. {
  850. int i;
  851. ORDDEF *odp;
  852. spec32->file_name = xstrdup( spec16->file_name );
  853. spec32->characteristics = IMAGE_FILE_DLL;
  854. spec32->init_func = xstrdup( "DllMain" );
  855. /* add an export for the NE module */
  856. odp = add_entry_point( spec32 );
  857. odp->type = TYPE_EXTERN;
  858. odp->flags = FLAG_PRIVATE;
  859. odp->name = xstrdup( "__wine_spec_dos_header" );
  860. odp->lineno = 0;
  861. odp->ordinal = 1;
  862. odp->link_name = xstrdup( ".L__wine_spec_dos_header" );
  863. if (spec16->main_module)
  864. {
  865. odp = add_entry_point( spec32 );
  866. odp->type = TYPE_EXTERN;
  867. odp->flags = FLAG_PRIVATE;
  868. odp->name = xstrdup( "__wine_spec_main_module" );
  869. odp->lineno = 0;
  870. odp->ordinal = 2;
  871. odp->link_name = xstrdup( ".L__wine_spec_main_module" );
  872. }
  873. /* add the explicit win32 exports */
  874. for (i = 1; i <= spec16->limit; i++)
  875. {
  876. ORDDEF *odp16 = spec16->ordinals[i];
  877. if (!odp16 || !odp16->name) continue;
  878. if (!(odp16->flags & FLAG_EXPORT32)) continue;
  879. odp = add_entry_point( spec32 );
  880. odp->flags = odp16->flags & ~FLAG_EXPORT32;
  881. odp->type = odp16->type;
  882. odp->name = xstrdup( odp16->name );
  883. odp->lineno = odp16->lineno;
  884. odp->ordinal = -1;
  885. odp->link_name = xstrdup( odp16->link_name );
  886. odp->u.func.nb_args = odp16->u.func.nb_args;
  887. if (odp->u.func.nb_args > 0) memcpy( odp->u.func.args, odp16->u.func.args,
  888. odp->u.func.nb_args * sizeof(odp->u.func.args[0]) );
  889. }
  890. assign_names( spec32 );
  891. assign_ordinals( spec32 );
  892. }
  893. /*******************************************************************
  894. * parse_spec_file
  895. *
  896. * Parse a .spec file.
  897. */
  898. int parse_spec_file( FILE *file, DLLSPEC *spec )
  899. {
  900. const char *token;
  901. input_file = file;
  902. current_line = 0;
  903. comment_chars = "#;";
  904. separator_chars = "()";
  905. while (get_next_line())
  906. {
  907. if (!(token = GetToken(1))) continue;
  908. if (strcmp(token, "@") == 0)
  909. {
  910. if (!parse_spec_ordinal( -1, spec )) continue;
  911. }
  912. else if (IsNumberString(token))
  913. {
  914. if (!parse_spec_ordinal( atoi(token), spec )) continue;
  915. }
  916. else if (strcmp(token, "apiset") == 0)
  917. {
  918. if (!parse_spec_apiset( spec )) continue;
  919. }
  920. else
  921. {
  922. error( "Expected ordinal declaration, got '%s'\n", token );
  923. continue;
  924. }
  925. if ((token = GetToken(1))) error( "Syntax error near '%s'\n", token );
  926. }
  927. current_line = 0; /* no longer parsing the input file */
  928. assign_names( spec );
  929. assign_ordinals( spec );
  930. return !nb_errors;
  931. }
  932. /*******************************************************************
  933. * parse_def_library
  934. *
  935. * Parse a LIBRARY declaration in a .def file.
  936. */
  937. static int parse_def_library( DLLSPEC *spec )
  938. {
  939. const char *token = GetToken(1);
  940. if (!token) return 1;
  941. if (strcmp( token, "BASE" ))
  942. {
  943. free( spec->file_name );
  944. spec->file_name = xstrdup( token );
  945. if (!(token = GetToken(1))) return 1;
  946. }
  947. if (strcmp( token, "BASE" ))
  948. {
  949. error( "Expected library name or BASE= declaration, got '%s'\n", token );
  950. return 0;
  951. }
  952. if (!(token = GetToken(0))) return 0;
  953. if (strcmp( token, "=" ))
  954. {
  955. error( "Expected '=' after BASE, got '%s'\n", token );
  956. return 0;
  957. }
  958. if (!(token = GetToken(0))) return 0;
  959. /* FIXME: do something with base address */
  960. return 1;
  961. }
  962. /*******************************************************************
  963. * parse_def_stack_heap_size
  964. *
  965. * Parse a STACKSIZE or HEAPSIZE declaration in a .def file.
  966. */
  967. static int parse_def_stack_heap_size( int is_stack, DLLSPEC *spec )
  968. {
  969. const char *token = GetToken(0);
  970. char *end;
  971. unsigned long size;
  972. if (!token) return 0;
  973. size = strtoul( token, &end, 0 );
  974. if (*end)
  975. {
  976. error( "Invalid number '%s'\n", token );
  977. return 0;
  978. }
  979. if (is_stack) spec->stack_size = size / 1024;
  980. else spec->heap_size = size / 1024;
  981. if (!(token = GetToken(1))) return 1;
  982. if (strcmp( token, "," ))
  983. {
  984. error( "Expected ',' after size, got '%s'\n", token );
  985. return 0;
  986. }
  987. if (!(token = GetToken(0))) return 0;
  988. /* FIXME: do something with reserve size */
  989. return 1;
  990. }
  991. /*******************************************************************
  992. * parse_def_export
  993. *
  994. * Parse an export declaration in a .def file.
  995. */
  996. static int parse_def_export( char *name, DLLSPEC *spec )
  997. {
  998. int i, args;
  999. const char *token = GetToken(1);
  1000. ORDDEF *odp = add_entry_point( spec );
  1001. odp->lineno = current_line;
  1002. odp->ordinal = -1;
  1003. odp->name = name;
  1004. args = remove_stdcall_decoration( odp->name );
  1005. if (args == -1)
  1006. {
  1007. odp->type = TYPE_CDECL;
  1008. args = 0;
  1009. }
  1010. else
  1011. {
  1012. odp->type = TYPE_STDCALL;
  1013. args /= get_ptr_size();
  1014. if (args >= MAX_ARGUMENTS)
  1015. {
  1016. error( "Too many arguments in stdcall function '%s'\n", odp->name );
  1017. return 0;
  1018. }
  1019. for (i = 0; i < args; i++) odp->u.func.args[i] = ARG_LONG;
  1020. }
  1021. odp->u.func.nb_args = args;
  1022. /* check for optional internal name */
  1023. if (token && !strcmp( token, "=" ))
  1024. {
  1025. if (!(token = GetToken(0))) goto error;
  1026. odp->link_name = xstrdup( token );
  1027. remove_stdcall_decoration( odp->link_name );
  1028. token = GetToken(1);
  1029. }
  1030. else
  1031. {
  1032. odp->link_name = xstrdup( name );
  1033. }
  1034. /* check for optional ordinal */
  1035. if (token && token[0] == '@')
  1036. {
  1037. int ordinal;
  1038. if (!IsNumberString( token+1 ))
  1039. {
  1040. error( "Expected number after '@', got '%s'\n", token+1 );
  1041. goto error;
  1042. }
  1043. ordinal = atoi( token+1 );
  1044. if (!ordinal)
  1045. {
  1046. error( "Ordinal 0 is not valid\n" );
  1047. goto error;
  1048. }
  1049. if (ordinal >= MAX_ORDINALS)
  1050. {
  1051. error( "Ordinal number %d too large\n", ordinal );
  1052. goto error;
  1053. }
  1054. odp->ordinal = ordinal;
  1055. token = GetToken(1);
  1056. }
  1057. /* check for other optional keywords */
  1058. while (token)
  1059. {
  1060. if (!strcmp( token, "NONAME" ))
  1061. {
  1062. if (odp->ordinal == -1)
  1063. {
  1064. error( "NONAME requires an ordinal\n" );
  1065. goto error;
  1066. }
  1067. odp->export_name = odp->name;
  1068. odp->name = NULL;
  1069. odp->flags |= FLAG_NONAME;
  1070. }
  1071. else if (!strcmp( token, "PRIVATE" ))
  1072. {
  1073. odp->flags |= FLAG_PRIVATE;
  1074. }
  1075. else if (!strcmp( token, "DATA" ))
  1076. {
  1077. odp->type = TYPE_EXTERN;
  1078. }
  1079. else
  1080. {
  1081. error( "Garbage text '%s' found at end of export declaration\n", token );
  1082. goto error;
  1083. }
  1084. token = GetToken(1);
  1085. }
  1086. return 1;
  1087. error:
  1088. spec->nb_entry_points--;
  1089. free( odp->name );
  1090. return 0;
  1091. }
  1092. /*******************************************************************
  1093. * parse_def_file
  1094. *
  1095. * Parse a .def file.
  1096. */
  1097. int parse_def_file( FILE *file, DLLSPEC *spec )
  1098. {
  1099. const char *token;
  1100. int in_exports = 0;
  1101. input_file = file;
  1102. current_line = 0;
  1103. comment_chars = ";";
  1104. separator_chars = ",=";
  1105. while (get_next_line())
  1106. {
  1107. if (!(token = GetToken(1))) continue;
  1108. if (!strcmp( token, "LIBRARY" ) || !strcmp( token, "NAME" ))
  1109. {
  1110. if (!parse_def_library( spec )) continue;
  1111. goto end_of_line;
  1112. }
  1113. else if (!strcmp( token, "STACKSIZE" ))
  1114. {
  1115. if (!parse_def_stack_heap_size( 1, spec )) continue;
  1116. goto end_of_line;
  1117. }
  1118. else if (!strcmp( token, "HEAPSIZE" ))
  1119. {
  1120. if (!parse_def_stack_heap_size( 0, spec )) continue;
  1121. goto end_of_line;
  1122. }
  1123. else if (!strcmp( token, "EXPORTS" ))
  1124. {
  1125. in_exports = 1;
  1126. if (!(token = GetToken(1))) continue;
  1127. }
  1128. else if (!strcmp( token, "IMPORTS" ))
  1129. {
  1130. in_exports = 0;
  1131. if (!(token = GetToken(1))) continue;
  1132. }
  1133. else if (!strcmp( token, "SECTIONS" ))
  1134. {
  1135. in_exports = 0;
  1136. if (!(token = GetToken(1))) continue;
  1137. }
  1138. if (!in_exports) continue; /* ignore this line */
  1139. if (!parse_def_export( xstrdup(token), spec )) continue;
  1140. end_of_line:
  1141. if ((token = GetToken(1))) error( "Syntax error near '%s'\n", token );
  1142. }
  1143. current_line = 0; /* no longer parsing the input file */
  1144. assign_names( spec );
  1145. assign_ordinals( spec );
  1146. return !nb_errors;
  1147. }