parser.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. #ident "@(#)parser.c 1.5 01/04/11"
  2. /** BEGIN COPYRIGHT BLOCK
  3. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  4. * Copyright (C) 2006 Red Hat, Inc.
  5. * All rights reserved.
  6. *
  7. * License: GPL (version 3 or any later version).
  8. * See LICENSE for details.
  9. * END COPYRIGHT BLOCK **/
  10. #ifdef HAVE_CONFIG_H
  11. # include <config.h>
  12. #endif
  13. /*
  14. FILE : parser.c
  15. AUTHOR : Jean-Luc SCHWING
  16. VERSION : 1.0
  17. DATE : 19 March 2001
  18. DESCRIPTION :
  19. This file contains the parser functions of ldclt
  20. LOCAL : None.
  21. HISTORY :
  22. ---------+--------------+------------------------------------------------------
  23. dd/mm/yy | Author | Comments
  24. ---------+--------------+------------------------------------------------------
  25. 19/03/01 | JL Schwing | Creation
  26. ---------+--------------+------------------------------------------------------
  27. 21/03/01 | JL Schwing | 1.2 : Implements variables in "-e object=filename"
  28. ---------+--------------+------------------------------------------------------
  29. 23/03/01 | JL Schwing | 1.3 : Implements data file list support in variants.
  30. | Bug fix : close the file !
  31. | Implements "-e rdn=value".
  32. ---------+--------------+------------------------------------------------------
  33. 28/03/01 | JL Schwing | 1.4 : Support -e commoncounter with -e rdn/object
  34. ---------+--------------+------------------------------------------------------
  35. 11/04/01 | JL Schwing | 1.5 : Implement [INCRFROMFILE<NOLOOP>(myfile)]
  36. | Improved error message.
  37. ---------+--------------+------------------------------------------------------
  38. */
  39. #include <stdio.h> /* printf(), etc... */
  40. #include <string.h> /* strcpy(), etc... */
  41. #include <errno.h> /* errno, etc... */
  42. #include <stdlib.h> /* malloc(), etc... */
  43. #include <lber.h> /* ldap C-API BER declarations */
  44. #include <ldap.h> /* ldap C-API declarations */
  45. #ifdef LDAP_H_FROM_QA_WKA
  46. #include <proto-ldap.h> /* ldap C-API prototypes */
  47. #endif
  48. #include <unistd.h> /* close(), etc... */
  49. #include <pthread.h> /* pthreads(), etc... */
  50. #include "port.h" /* Portability definitions */
  51. #include "ldclt.h" /* This tool's include file */
  52. #include "utils.h" /* Utilities functions */
  53. /* ****************************************************************************
  54. FUNCTION : decodeHow
  55. PURPOSE : Decode the how field
  56. INPUT : how = field to decode
  57. OUTPUT : None.
  58. RETURN : -1 if error, how value else.
  59. DESCRIPTION :
  60. *****************************************************************************/
  61. int
  62. decodeHow (
  63. char *how)
  64. {
  65. if (mctx.mode & VERY_VERBOSE)
  66. printf ("decodeHow: how=\"%s\"\n", how);
  67. if (!strcmp (how, "INCRFROMFILE")) return (HOW_INCR_FROM_FILE);
  68. if (!strcmp (how, "INCRFROMFILENOLOOP")) return (HOW_INCR_FROM_FILE_NL);
  69. if (!strcmp (how, "INCRN")) return (HOW_INCR_NB);
  70. if (!strcmp (how, "INCRNNOLOOP")) return (HOW_INCR_NB_NOLOOP);
  71. if (!strcmp (how, "RNDFROMFILE")) return (HOW_RND_FROM_FILE);
  72. if (!strcmp (how, "RNDN")) return (HOW_RND_NUMBER);
  73. if (!strcmp (how, "RNDS")) return (HOW_RND_STRING);
  74. return (-1);
  75. }
  76. /* ****************************************************************************
  77. FUNCTION : parseVariant
  78. PURPOSE : Parse a variant definition.
  79. INPUT : variant = string to parse
  80. fname = file name
  81. line = source line
  82. obj = object we are parsing and building
  83. OUTPUT : field = field parsed
  84. RETURN : -1 if error, 0 else.
  85. DESCRIPTION :
  86. *****************************************************************************/
  87. int
  88. parseVariant (
  89. char *variant,
  90. char *fname,
  91. char *line,
  92. vers_object *obj,
  93. vers_field *field)
  94. {
  95. int start, end; /* For the loops */
  96. char how[MAX_FILTER]; /* To parse the variant : */
  97. char first[MAX_FILTER]; /* how(first) */
  98. char second[MAX_FILTER]; /* how(first,second) */
  99. char third[MAX_FILTER]; /* how(first,second,third) */
  100. int ret; /* ldclt_mutex_init() return value */
  101. if (mctx.mode & VERY_VERBOSE)
  102. printf ("parseVariant: variant=\"%s\"\n", variant);
  103. /*
  104. * Maybe a variable ?
  105. */
  106. if (variant[1] == '\0')
  107. {
  108. if ((variant[0] < VAR_MIN) || (variant[0] > VAR_MAX))
  109. {
  110. fprintf (stderr, "Error: bad variable in %s : \"%s\"\n", fname, line);
  111. fprintf (stderr, "Error: must be in [%c-%c]\n", VAR_MIN, VAR_MAX);
  112. return (-1);
  113. }
  114. field->how = HOW_VARIABLE;
  115. field->var = variant[0] - VAR_MIN;
  116. return (0);
  117. }
  118. /*
  119. * Maybe a variable definition ?
  120. */
  121. if (variant[1] != '=')
  122. field->var = -1;
  123. else
  124. {
  125. if ((variant[0] < VAR_MIN) || (variant[0] > VAR_MAX))
  126. {
  127. fprintf (stderr, "Error: bad variable in %s : \"%s\"\n", fname, line);
  128. fprintf (stderr, "Error: must be in [%c-%c]\n", VAR_MIN, VAR_MAX);
  129. return (-1);
  130. }
  131. field->var = variant[0] - VAR_MIN;
  132. variant++; /* Skip variable name */
  133. variant++; /* Skip '=' */
  134. /*
  135. * We need a variable !
  136. */
  137. if (obj->var[field->var] == NULL)
  138. obj->var[field->var] = (char *) malloc (MAX_FILTER);
  139. }
  140. /*
  141. * Find how definition
  142. */
  143. for (end=0 ; (variant[end]!='\0') && (variant[end]!='(') ; end++);
  144. if (variant[end]=='\0')
  145. {
  146. fprintf (stderr, "Error: bad variant in %s : \"%s\"\n", fname, line);
  147. fprintf (stderr, "Error: missing '('\n");
  148. return (-1);
  149. }
  150. strncpy (how, variant, end);
  151. how[end] = '\0';
  152. /*
  153. * Parse the first parameter
  154. */
  155. end++; /* Skip '(' */
  156. for (start=end ; (variant[end]!='\0') && (variant[end]!=';')
  157. && (variant[end]!=')') ; end++);
  158. if (variant[end]=='\0')
  159. {
  160. fprintf (stderr, "Error: bad variant in %s : \"%s\"\n", fname, line);
  161. fprintf (stderr, "Error: missing ')'\n");
  162. return (-1);
  163. }
  164. strncpy (first, variant+start, end-start);
  165. first[end-start] = '\0';
  166. /*
  167. * Parse the second parameter
  168. */
  169. if (variant[end] == ')')
  170. second[0] = '\0';
  171. else
  172. {
  173. end++; /* Skip ';' */
  174. for (start=end ; (variant[end]!='\0') && (variant[end]!=';')
  175. && (variant[end]!=')') ; end++);
  176. if (variant[end]=='\0')
  177. {
  178. fprintf (stderr, "Error: bad variant in %s : \"%s\"\n", fname, line);
  179. fprintf (stderr, "Error: missing ')'\n");
  180. return (-1);
  181. }
  182. strncpy (second, variant+start, end-start);
  183. second[end-start] = '\0';
  184. }
  185. /*
  186. * Parse the third parameter
  187. */
  188. if (variant[end]==')')
  189. third[0]='\0';
  190. else
  191. {
  192. end++; /* Skip ';' */
  193. for (start=end ; (variant[end]!='\0') && (variant[end]!=')') ; end++);
  194. if (variant[end]=='\0')
  195. {
  196. fprintf (stderr, "Error: bad variant in %s : \"%s\"\n", fname, line);
  197. fprintf (stderr, "Error: missing ')'\n");
  198. return (-1);
  199. }
  200. strncpy (third, variant+start, end-start);
  201. third[end-start] = '\0';
  202. }
  203. /*
  204. * Analyse it
  205. * Note : first parameter always exist (detected when parsing) while
  206. * second and third may not have been provided by the user.
  207. */
  208. switch (field->how = decodeHow (how))
  209. {
  210. case HOW_INCR_FROM_FILE:
  211. case HOW_INCR_FROM_FILE_NL:
  212. case HOW_RND_FROM_FILE:
  213. if ((field->dlf = dataListFile (first)) == NULL)
  214. {
  215. fprintf (stderr, "Error : bad file in %s : \"%s\"\n", fname, line);
  216. return (-1);
  217. }
  218. /*
  219. * Useless for HOW_RND_FROM_FILE
  220. */
  221. field->cnt = 0;
  222. field->low = 0;
  223. field->high = field->dlf->strNb - 1;
  224. /*
  225. * Maybe common counter ?
  226. */
  227. if ((mctx.mode & COMMON_COUNTER) &&
  228. ((field->how == HOW_INCR_FROM_FILE) ||
  229. (field->how == HOW_INCR_FROM_FILE_NL)))
  230. {
  231. if ((ret = ldclt_mutex_init (&(field->cnt_mutex))) != 0)
  232. {
  233. fprintf (stderr, "ldclt: %s\n", strerror (ret));
  234. fprintf (stderr, "Error: cannot initiate cnt_mutex in %s for %s\n",
  235. fname, line);
  236. fflush (stderr);
  237. return (-1);
  238. }
  239. }
  240. break;
  241. case HOW_INCR_NB:
  242. case HOW_INCR_NB_NOLOOP:
  243. case HOW_RND_NUMBER:
  244. if (third[0] == '\0')
  245. {
  246. fprintf (stderr, "Error : missing parameters in %s : \"%s\"\n",
  247. fname, line);
  248. return (-1);
  249. }
  250. field->cnt = atoi (first);
  251. field->low = atoi (first);
  252. field->high = atoi (second);
  253. field->nb = atoi (third);
  254. /*
  255. * Maybe common counter ?
  256. */
  257. if ((mctx.mode & COMMON_COUNTER) &&
  258. ((field->how == HOW_INCR_NB) || (field->how == HOW_INCR_NB_NOLOOP)))
  259. {
  260. if ((ret = ldclt_mutex_init (&(field->cnt_mutex))) != 0)
  261. {
  262. fprintf (stderr, "ldclt: %s\n", strerror (ret));
  263. fprintf (stderr, "Error: cannot initiate cnt_mutex in %s for %s\n",
  264. fname, line);
  265. fflush (stderr);
  266. return (-1);
  267. }
  268. }
  269. break;
  270. case HOW_RND_STRING:
  271. field->nb = atoi (first);
  272. break;
  273. case -1:
  274. fprintf (stderr, "Error: illegal keyword \"%s\" in %s : \"%s\"\n",
  275. how, fname, line);
  276. return (-1);
  277. break;
  278. }
  279. return (0);
  280. }
  281. /* ****************************************************************************
  282. FUNCTION : parseAttribValue
  283. PURPOSE : Parse the right part of attribname: attribvalue.
  284. INPUT : fname = file name
  285. obj = object where variables are.
  286. line = value to parse.
  287. OUTPUT : attrib = attribute where the value should be stored
  288. RETURN : -1 if error, 0 else.
  289. DESCRIPTION :
  290. *****************************************************************************/
  291. int
  292. parseAttribValue (
  293. char *fname,
  294. vers_object *obj,
  295. char *line,
  296. vers_attribute *attrib)
  297. {
  298. char variant[MAX_FILTER]; /* To process the variant */
  299. int start, end; /* For the loops */
  300. vers_field *field; /* To build the fields */
  301. if (mctx.mode & VERY_VERBOSE)
  302. printf ("parseAttribValue: line=\"%s\"\n", line);
  303. /*
  304. * We will now parse this line for the different fields.
  305. */
  306. field = NULL;
  307. end = start = 0;
  308. while (line[end]!='\0')
  309. {
  310. /*
  311. * Allocate a new field
  312. */
  313. if (field == NULL)
  314. {
  315. field = (vers_field *) malloc (sizeof (vers_field));
  316. field->next = NULL;
  317. attrib->field = field;
  318. }
  319. else
  320. {
  321. field->next = (vers_field *) malloc (sizeof (vers_field));
  322. field = field->next;
  323. field->next = NULL;
  324. }
  325. /*
  326. * Is it a variant field ?
  327. */
  328. if (line[end] == '[')
  329. {
  330. /*
  331. * Extract the variant definition
  332. */
  333. end++; /* Skip '[' */
  334. for (start=end ; (line[end]!='\0') && (line[end]!=']') ; end++);
  335. strncpy (variant, line+start, end-start);
  336. variant[end-start] = '\0';
  337. if (line[end]=='\0')
  338. {
  339. fprintf (stderr, "Error: missing ']' in %s : \"%s\"\n", fname, line);
  340. return (-1);
  341. }
  342. if (parseVariant (variant, fname, line, obj, field) < 0)
  343. return (-1);
  344. end++; /* Skip ']' */
  345. /*
  346. * We need to allocate a buffer in this attribute !
  347. */
  348. if (attrib->buf == NULL)
  349. {
  350. attrib->buf = (char *) malloc (MAX_FILTER);
  351. if (mctx.mode & VERY_VERBOSE)
  352. printf ("parseAttribValue: buffer allocated\n");
  353. }
  354. }
  355. else
  356. {
  357. /*
  358. * It is a constant field. Find the end : [ or \0
  359. */
  360. for (start=end ; (line[end]!='\0') && (line[end]!='[') ; end++);
  361. field->how = HOW_CONSTANT;
  362. field->cst = (char *) malloc (1+end-start);
  363. strncpy (field->cst, line+start, end-start);
  364. field->cst[end-start] = '\0';
  365. }
  366. }
  367. /*
  368. * Attribute value is parsed !
  369. */
  370. return (0);
  371. }
  372. /* ****************************************************************************
  373. FUNCTION : parseLine
  374. PURPOSE : Parse the given line to find an attribute definition.
  375. INPUT : line = line to parse
  376. fname = file name
  377. OUTPUT : obj = object where the attribute should be added
  378. RETURN : -1 if error, 0 else.
  379. DESCRIPTION :
  380. *****************************************************************************/
  381. int
  382. parseLine (
  383. char *line,
  384. char *fname,
  385. vers_object *obj)
  386. {
  387. int end; /* For the loops */
  388. if (mctx.mode & VERY_VERBOSE)
  389. printf ("parseLine: line=\"%s\"\n", line);
  390. /*
  391. * Empty line ? Comment ?
  392. * No more place for new attributes ?
  393. */
  394. if ((line[0]=='\0') || (line[0]=='#'))
  395. return (0);
  396. if (obj->attribsNb == MAX_ATTRIBS)
  397. {
  398. fprintf (stderr, "Error: too many attributes in %s, max is %d\n",
  399. fname, MAX_ATTRIBS);
  400. return (-1);
  401. }
  402. /*
  403. * Find the attribute name
  404. * name:
  405. */
  406. for (end=0 ; (line[end]!='\0') && (line[end]!=':') ; end++);
  407. if (line[end]!=':')
  408. {
  409. fprintf (stderr, "Error: can't find attribute name in %s : \"%s\"\n",
  410. fname, line);
  411. return (-1);
  412. }
  413. /*
  414. * Initiate the attribute
  415. */
  416. obj->attribs[obj->attribsNb].buf = NULL;
  417. obj->attribs[obj->attribsNb].src = strdup (line);
  418. obj->attribs[obj->attribsNb].name = (char *) malloc (1+end);
  419. strncpy (obj->attribs[obj->attribsNb].name, line, end);
  420. obj->attribs[obj->attribsNb].name[end] = '\0';
  421. for (end++ ; line[end]==' ' ; end++); /* Skip the leading ' ' */
  422. /*
  423. * We will now parse the value of this attribute
  424. */
  425. if (parseAttribValue(fname,obj, line+end, &(obj->attribs[obj->attribsNb]))<0)
  426. return (-1);
  427. /*
  428. * Do not forget to increment attributes number !
  429. */
  430. obj->attribsNb++;
  431. return (0);
  432. }
  433. /* ****************************************************************************
  434. FUNCTION : readObject
  435. PURPOSE : This function will read an object description from the
  436. file given in argument.
  437. The object should be already initiated !!!
  438. INPUT : None.
  439. OUTPUT : obj = parsed object.
  440. RETURN : -1 if error, 0 else.
  441. DESCRIPTION :
  442. *****************************************************************************/
  443. int
  444. readObject (
  445. vers_object *obj)
  446. {
  447. FILE *ifile; /* The file that contains the object to read */
  448. char line[MAX_FILTER]; /* To read ifile */
  449. int rc = 0;
  450. /*
  451. * Open the file
  452. */
  453. ifile = fopen (obj->fname, "r");
  454. if (ifile == NULL)
  455. {
  456. perror (obj->fname);
  457. fprintf (stderr, "Error: cannot open file \"%s\"\n", obj->fname);
  458. rc = -1;
  459. goto done;
  460. }
  461. /*
  462. * Process each line of the input file.
  463. * Reminder : the object is initiated by the calling function !
  464. */
  465. while (fgets (line, MAX_FILTER, ifile) != NULL)
  466. {
  467. if ((strlen (line) > 0) && (line[strlen(line)-1]=='\n'))
  468. line[strlen(line)-1] = '\0';
  469. if (parseLine (line, obj->fname, obj) < 0) {
  470. rc = -1;
  471. goto done;
  472. }
  473. }
  474. done:
  475. /*
  476. * Do not forget to close the file !
  477. */
  478. if (ifile && fclose (ifile) != 0)
  479. {
  480. perror (obj->fname);
  481. fprintf (stderr, "Error: cannot fclose file \"%s\"\n", obj->fname);
  482. rc = -1;
  483. }
  484. /*
  485. * End of function
  486. */
  487. if (obj->attribsNb == 0)
  488. {
  489. fprintf (stderr, "Error: no object found in \"%s\"\n", obj->fname);
  490. rc = -1;
  491. }
  492. return rc;
  493. }