[driver-gen-git] Add git library files.
[driver-gen.git] / driverGen.c
blob22326aed0669f7e06a4b0161da56c1da8de87008
1 /**
2 * @file driverGen.c
4 * @brief Pulling everything together.
6 * @author Copyright (c) 2004 - 2009 CERN. Georgievskiy Yury, Alain Gagnaire
8 * @date Created on 27/02/2004
10 * Device Driver Generator (aka DriverGen) tool designed to produce
11 * device drivers for a given architecture based on an abstract description
12 * of a piece of hardware.
14 #define _GNU_SOURCE /* asprintf rocks */
15 #include <getopt.h>
16 #include "driverGen.h"
17 #include "utilities.h"
18 #include "serviceOptions.h"
19 #include "dg-version.h"
20 #include "dg-git-lib.h"
22 struct mdescr dgmd = { 0 }; /* Driver-Gen Module Description */
24 bool verboseMode; /* denotes verbose driver generation */
25 static dgopt genOpt; /* possible command line options */
26 static srvarg glob_srv_arg; /* possible service option arguments */
27 char *driverName; /* Driver Name. Exactly as in the DataBase */
28 char *busType; /* bus type. 'vme' or 'pci' */
29 time_t mod_creation_time; /* driver creation time of the currently
30 processed module */
32 /* supported buses */
33 static char *allBuses[] = {
34 "vme",
35 "VME",
36 "pci",
37 "PCI",
38 NULL
41 /* supported command line options */
42 static struct option allLongOptions[] = {
43 { "git", no_argument, NULL, 'g' },
44 { "gall", no_argument, NULL, 'a' },
45 { "ginfo", no_argument, NULL, 'i' },
46 { "general", required_argument, NULL, 'e' },
47 { "verbose", no_argument, NULL, 'n' },
48 { "srv", required_argument, NULL, 's' }, /* see 'serviceOptions.h'
49 for more information */
50 { "dir", required_argument, NULL, 'd' },
51 { "version", no_argument, NULL, 'v' },
52 { "help", no_argument, NULL, 'h' },
54 .name = 0,
55 .has_arg = no_argument, /* 0 */
56 .flag = 0,
57 .val = 0
61 static int CheckAndPrepareRegs(RegisterDef_t *, int, VmeInfo_t *);
62 static int CheckAndPrepareBlocks(BlockDef_t *, int);
63 static void SortRegisters(RegisterDef_t *, VmeInfo_t *, int, int);
64 static int LessThan(RegisterDef_t *, RegisterDef_t *);
65 static int GreaterThan(RegisterDef_t *, RegisterDef_t *);
66 static void SortBlocks(BlockDef_t *, int, int);
67 static bool CheckBusType(char *);
68 static void DisplayUsage(char *);
69 static void ParseProgArgs(int, char *[], struct mdescr *);
70 static void free_md(struct mdescr *);
72 int main(int argc, char *argv[], char *envp[])
74 int numRegisters;
75 int numBlocks;
76 rstat result;
77 RegisterDef_t registers[MAX_REG] = { {0} };
78 BlockDef_t blocks[MAX_BLK] = { {0} };
79 PciInfo_t pciInfo;
80 VmeInfo_t vmeInfo;
82 /* Init default parameters */
83 vmeInfo.CheckRegister = -1; /* no checking register */
84 verboseMode = FALSE; /* by default - no verbose mode */
86 ParseProgArgs(argc, argv, &dgmd); /* check if provided params are valid */
87 time(&mod_creation_time);
88 printf("%s <vers. %s> started on %s\n", basename(argv[0]), dg_version,
89 ctime(&mod_creation_time));
91 /* init global template values for further use */
92 TranslationInit(driverName, busType);
94 /* if only general shared code should be build */
95 if (genOpt == OPT_G_SHARED) {
96 BuildGeneralCode();
97 printf("%s: All done.\n", basename(argv[0]));
98 exit(EXIT_SUCCESS);
101 /* if it's one of the service calls */
102 if (genOpt == OPT_G_SERVICE) {
103 if (ProcessSrvOpt(glob_srv_arg, basename(argv[0]))) {
104 printf("%s: service option processing fails\n",
105 argv[0]);
106 exit(EXIT_FAILURE);
107 } else {
108 printf("%s: service option processing done.\n",
109 argv[0]);
110 exit(EXIT_SUCCESS);
114 /* get block configuration from database */
115 if (!(numBlocks = GetBlockConfig(driverName, blocks, argv[0]))) {
116 fprintf(stderr, "%s No Blocks found for %s Module\n", ERROR_MSG,
117 driverName);
118 exit(EXIT_FAILURE);
121 /* check if block configuration is correct */
122 if (CheckAndPrepareBlocks(blocks, numBlocks) != DRIVER_GEN_OK)
123 exit(EXIT_FAILURE);
125 /* get register configuration from database */
126 numRegisters = GetRegisterConfig(driverName, registers, blocks,
127 numBlocks, argv[0]);
128 if (!numRegisters) {
129 fprintf(stderr, "%s No Registers found for %s Module\n",
130 ERROR_MSG, driverName);
131 exit(EXIT_FAILURE);
134 /* check if register configuration is correct */
135 if (CheckAndPrepareRegs(registers, numRegisters, &vmeInfo) !=
136 DRIVER_GEN_OK)
137 exit(EXIT_FAILURE);
139 /* we need to compute block sizes and their register amount */
140 set_extra_block_data(registers);
142 /* get general board information from the database */
143 if (!strcmp(TranslationGetBus(), "VME"))
144 result = GetVmeInfo(driverName, &vmeInfo);
145 else
146 result = GetPciInfo(driverName, &pciInfo);
148 if (result)
149 exit(EXIT_FAILURE); /* 1 */
151 /* now we can start Driver/Simulator code generation */
152 printf("Creating %s source code directory.\n", driverName);
154 /* setup Master installation and Module source directories */
155 get_mid(&dgmd);
156 get_msd(&dgmd);
158 if (!strcmp(TranslationGetBus(), "VME")) { /* we need VME driver */
159 switch (genOpt) {
160 case OPT_G_IT:
161 GenerateVmeDriver(registers, numRegisters, blocks,
162 numBlocks, &vmeInfo);
163 git_embrace(&dgmd);
164 break;
165 case OPT_G_ALL: /* generate all, include user-defined files */
166 GenerateVmeDriver(registers, numRegisters, blocks,
167 numBlocks, &vmeInfo);
168 break;
169 case OPT_G_INFO: /* generate only info files */
170 GenerateVmeInfoFile(registers, numRegisters, blocks,
171 numBlocks, &vmeInfo);
172 break;
173 default:
174 FATAL_ERR();
175 break; /* not reached */
177 } else { /* we need PCI driver */
178 switch (genOpt) {
179 case OPT_G_IT:
180 GenerateDrmDriver(registers, numRegisters, blocks,
181 numBlocks, &pciInfo);
182 git_embrace(&dgmd);
183 break;
184 case OPT_G_ALL: /* generate all, include user-defined files */
185 GenerateDrmDriver(registers, numRegisters, blocks,
186 numBlocks, &pciInfo);
187 break;
188 case OPT_G_INFO: /* generate only install files */
189 /* TODO. Should be removed. */
190 GenerateDrmInstallFilesOLD(&pciInfo, blocks, numBlocks);
191 break;
192 default:
193 FATAL_ERR();
194 break; /* not reached */
198 free_md(&dgmd);
199 printf("All done.\n");
200 exit(EXIT_SUCCESS); /* 0 */
204 * @brief Checks if module configuration is correct and supported.
206 * @param registers -- register description
207 * @param numRegisters -- register amount
208 * @param vmeInfo -- @b VME description
210 * @return DRIVER_GEN_OK - if configuration is ok.
211 * @return DRIVER_GEN_BAD - othervise.
213 static int CheckAndPrepareRegs(RegisterDef_t * registers, int numRegisters,
214 VmeInfo_t * vmeInfo)
216 int i, j;
217 int badConfig = DRIVER_GEN_OK;
218 int mappedAddr = 0; /* checked address range */
219 int regDepth; /* register depth, in elements */
221 for (i = 0; i < numRegisters; i++) { /* Sanitise register definition */
222 StrToLower(registers[i].size);
223 StrToLower(registers[i].mode);
224 registers[i].rar = 0;
225 for (j = 0; j < strlen(registers[i].mode); j++) {
226 if (registers[i].mode[j] == 'w') {
227 registers[i].rar |= AMWR;
228 } else if (registers[i].mode[j] == 'r') {
229 registers[i].rar |= AMRD;
230 } else if (registers[i].mode[j] == 'e') {
231 registers[i].rar |= AMEX;
232 } else if (registers[i].mode[j] == 'c') {
233 vmeInfo->CheckRegister = i;
234 } else {
235 badConfig = DRIVER_GEN_BAD;
236 fprintf(stderr, "%s Register '%s' has unknown"
237 " access mode '%c'\n",
238 ERROR_MSG, registers[i].name,
239 registers[i].mode[j]);
243 strcpy(registers[i].upperName, registers[i].name);
244 StrToUpper(registers[i].upperName);
246 if (!strcmp(registers[i].size, "char"))
247 registers[i].regSize = SZCHAR;
248 else if (!strcmp(registers[i].size, "short"))
249 registers[i].regSize = SZSHORT;
250 else if (!strcmp(registers[i].size, "long"))
251 registers[i].regSize = SZLONG;
252 else {
253 badConfig = DRIVER_GEN_BAD;
254 fprintf(stderr, "%s Register '%s' has incorrect size"
255 " name '%s'\n",
256 ERROR_MSG, registers[i].name,
257 registers[i].size);
260 /* Check if the data is valid */
261 if (registers[i].timeLoop < 0) {
262 badConfig = DRIVER_GEN_BAD;
263 fprintf(stderr, "%s Register '%s' has a negative"
264 " timeloop %d\n",
265 ERROR_MSG, registers[i].name,
266 registers[i].timeLoop);
269 for (j = 0; j < strlen(registers[i].name); j++)
270 if (isspace(registers[i].name[j]))
271 /* replace wite spaces with underscore */
272 registers[i].name[j] = '_';
274 for (j = i + 1; j < numRegisters; j++)
275 if (!strcmp(registers[i].name, registers[j].name)) {
276 badConfig = DRIVER_GEN_BAD;
277 fprintf(stderr, "%s Register definitions %d"
278 " and %d share the name \"%s\"\n",
279 ERROR_MSG, i, j, registers[i].name);
282 if (registers[i].rar > AMEX) {
283 fprintf(stderr, "%s Register '%s' has a conflicting"
284 " access mode '%s'\n",
285 ERROR_MSG, registers[i].name,
286 registers[i].mode);
287 sprintf(registers[i].mode, "e");
288 registers[i].rar = AMEX;
291 if ((!registers[i].blockP)) {
292 badConfig = DRIVER_GEN_BAD;
293 fprintf(stderr, "%s Register '%s' doesn't belong to"
294 " any block\n",
295 ERROR_MSG, registers[i].name);
298 if (registers[i].offset < 0) {
299 badConfig = DRIVER_GEN_BAD;
300 fprintf(stderr, "%s Register '%s' has negative offset"
301 " value '0x%x'\n",
302 ERROR_MSG, registers[i].name,
303 registers[i].offset);
305 } /* end of 'for' */
307 if (badConfig == DRIVER_GEN_BAD)
308 return badConfig;
310 /* sort registers by their address */
311 SortRegisters(registers, vmeInfo, 0, numRegisters - 1);
313 for (i = 0; i < numRegisters - 1; i++) {
315 if (registers[i].depth <= 0)
316 regDepth = 1;
317 else
318 regDepth = registers[i].depth;
320 /* check registers that belong to the same block only */
321 if (registers[i].blockP->blockID ==
322 registers[i + 1].blockP->blockID) {
323 /* check if there is duplicate register addresses
324 in the same block */
325 if (registers[i].offset == registers[i + 1].offset) {
326 badConfig = DRIVER_GEN_BAD;
327 fprintf(stderr, "%s Registers '%s' and '%s' in"
328 " Block#%d have the same offset %#x\n",
329 ERROR_MSG, registers[i].name,
330 registers[i + 1].name,
331 registers[i].blockP->blockID,
332 registers[i].offset);
334 mappedAddr =
335 registers[i].offset +
336 registers[i].regSize * regDepth;
337 if (mappedAddr > registers[i + 1].offset) {
338 fprintf(stderr, "%s Overlapping between '%s'"
339 " and '%s' register massives\n"
340 "\tdetected in Block#%d. Incorrect "
341 "device memory mapping. Try to "
342 "change\n\tmemory layout in the Data"
343 " Base.\n",
344 ERROR_MSG, registers[i].name,
345 registers[i + 1].name,
346 registers[i].blockP->blockID);
347 badConfig = DRIVER_GEN_BAD;
349 } else {
350 mappedAddr = 0;
354 if (badConfig == DRIVER_GEN_BAD)
355 return badConfig;
357 /* Check if device checking address is provided */
358 if (vmeInfo->CheckRegister == -1) {
359 fprintf(stderr, "%sChecking Register is NOT provided!\n"
360 " Module availability will NOT be checked"
361 " during device driver\n installation!\n\n",
362 WARNING_MSG);
363 sleep(2); /* let user see it */
366 return badConfig;
370 * @brief Checks if block configuration is correct and supported.
372 * @param blocks -- block description
373 * @param numBlocks -- block amount
375 * @return DRIVER_GEN_OK - if configuration is ok.
376 * @return DRIVER_GEN_BAD - othervise.
378 static int CheckAndPrepareBlocks(BlockDef_t * blocks, int numBlocks)
380 int i;
381 int configState = DRIVER_GEN_OK;
383 for (i = 0; i < numBlocks; i++) {
384 if (blocks[i].blockID < 0) {
385 fprintf(stderr, "%s GetBlockConfig() has returned a"
386 " record with a negative block number\n",
387 ERROR_MSG);
388 configState = DRIVER_GEN_BAD;
391 if ((blocks[i].blkBaseAddr < 1) ||
392 (blocks[i].blkBaseAddr > 2)) {
393 fprintf(stderr, "%s Block#%d is associated with"
394 " invalid base address value '%d'\n",
395 ERROR_MSG, blocks[i].blockID,
396 blocks[i].blkBaseAddr);
397 configState = DRIVER_GEN_BAD;
400 if (blocks[i].offset < 0) {
401 fprintf(stderr, "%s Block#%d has a negative offset"
402 " value\n",
403 ERROR_MSG, blocks[i].blockID);
404 configState = DRIVER_GEN_BAD;
408 if (configState == DRIVER_GEN_OK) {
409 SortBlocks(blocks, 0, numBlocks - 1);
410 for (i = 0; i < numBlocks - 1; i++)
411 if (blocks[i].blockID == blocks[i + 1].blockID) {
412 fprintf(stderr, "%s GetBlockConfig() has"
413 " returned two records with block ID's"
414 " equals to %d\n",
415 ERROR_MSG, blocks[i].blockID);
416 configState = DRIVER_GEN_BAD;
420 return configState;
424 * @brief Sort registers by their block indexes && addresses.
426 * @param registers -- register description table
427 * @param vmeInfo -- VME description
428 * @param low -- lowest index
429 * @param high -- highest index
431 static void SortRegisters(RegisterDef_t *registers, VmeInfo_t *vmeInfo,
432 int low, int high)
434 int left, right;
435 RegisterDef_t buffer;
436 RegisterDef_t *median;
438 if (high > low) {
439 left = low;
440 right = high;
441 median = &registers[low];
443 while (right >= low) {
444 while (LessThan(&(registers[left]), median))
445 left++;
447 while (GreaterThan(&(registers[right]), median))
448 right--;
450 if (left > right)
451 break;
453 buffer = registers[left];
454 registers[left] = registers[right];
455 registers[right] = buffer;
457 /* move checking register index */
458 if (vmeInfo->CheckRegister == left)
459 vmeInfo->CheckRegister = right;
460 else if (vmeInfo->CheckRegister == right)
461 vmeInfo->CheckRegister = left;
463 left++;
464 right--;
467 SortRegisters(registers, vmeInfo, low, right);
468 SortRegisters(registers, vmeInfo, left, high);
473 * @brief Check if register a is smaller then register b
475 * @param a -- reg descr
476 * @param b -- reg descr
478 * @return 1 - if first regID is smaller then the second one.
479 * @return 0 - otherwise.
481 static int LessThan(RegisterDef_t *a, RegisterDef_t *b)
483 if (a->blockP->blockID < b->blockP->blockID)
484 return 1;
485 else if ((a->blockP->blockID == b->blockP->blockID) &&
486 (a->offset < b->offset))
487 return 1;
488 else
489 return 0;
493 * @brief Check if register a is greater then register b
495 * @param a -- reg descr
496 * @param b -- reg descr
498 * @return 1 - if first regID is greater then the second one.
499 * @return 0 - otherwise.
501 static int GreaterThan(RegisterDef_t *a, RegisterDef_t *b)
503 if ((a->blockP->blockID == b->blockP->blockID)
504 && (a->offset == b->offset))
505 return 0;
506 else
507 return (!LessThan(a, b));
511 * @brief Sort blocks by their index
513 * @param blocks -- block description
514 * @param low -- low block idx
515 * @param high -- high block idx
517 * @return void
519 static void SortBlocks(BlockDef_t *blocks, int low, int high)
521 int left, right;
522 BlockDef_t buffer;
523 BlockDef_t *median;
525 if (high > low) {
526 left = low;
527 right = high;
528 median = &(blocks[low]);
530 while (right >= low) {
531 while (blocks[left].blockID < median->blockID)
532 left++;
534 while (blocks[right].blockID > median->blockID)
535 right--;
537 if (left > right)
538 break;
540 buffer = blocks[left];
541 blocks[left] = blocks[right];
542 blocks[right] = buffer;
543 left++;
544 right--;
547 SortBlocks(blocks, low, right);
548 SortBlocks(blocks, left, high);
553 * @brief Checks if the bus type parameter is correct.
555 * If it is not, than error is printed out on stderr.
557 * @param str -- string to check
559 * @return TRUE - if parameter is valid.
560 * @return FALSE - otherwise.
562 static bool CheckBusType(char *str)
564 bool res = FALSE;
565 char **ptr, errMsg[64];
567 ptr = allBuses;
568 snprintf(errMsg, sizeof(errMsg), "Bus type \'%s\' not supported.\n",
569 str);
571 while (*ptr) {
572 if (!(strcmp(*ptr, str))) { /* option matches */
573 res = TRUE;
574 break;
576 ptr++; /* move pointer */
579 if (!res)
580 fprintf(stderr, errMsg); /* printout error message. */
582 return (res);
586 * @brief Educate user
588 * @param progName -- program name
590 * @return void
592 static void DisplayUsage(char *progName)
594 progName = basename(progName);
595 printf("%s %s\n\n", progName, dg_version);
596 printf("Usage: %s <module_name> <bus> -g[it | all | info] "
597 "<-verbose> -d <root_dir>\n", progName);
598 printf(" %s <-general> <bus>\n", progName);
599 printf(" %s <-h> <--version> (to get help && version info)\n",
600 progName);
601 printf("where:\n");
603 /* module-name */
604 printf(" <module_name> %sCompulsory%s\n", WHITE_CLR, END_CLR);
605 printf(" It is the name of the module for which Driver/Simulator "
606 "should be generated.\n");
607 printf(" Should be exactly as in the DataBase. See DataBase for"
608 " more info about\n Module Names.\n\n");
610 /* bus */
611 printf(" <bus> %sCompulsory%s\n", WHITE_CLR, END_CLR);
612 printf(" Select the bus architecture supported by the card.\n");
613 printf(" Supported buses are 'pci' or 'vme'.\n\n");
615 /* '-g' mode description */
616 printf(" -g %sOptional%s\n"
617 " What to generate (if not provided -- default will be"
618 " used):\n", WHITE_CLR, END_CLR);
619 printf(" -g[all] %sDefault%s\n"
620 " Generate complete driver framework\n",
621 WHITE_CLR, END_CLR);
622 printf(" -g[it]\n"
623 " Generate git-controlled Driver, i.e. user-defined files"
624 " are generated\n"
625 " only if driver directory does not yet exist (otherwise"
626 " user-defined files\n"
627 " left intact), driver dir name doesn't have time prefix,"
628 " git-tag is\n"
629 " performed. (All files, that've got \"UserDefined\""
630 " subword in their\n"
631 " name -- are considered to be user-defined files)\n");
632 printf(" -g[info]\n"
633 " Generate only info file for current module.\n\n");
635 /* '-verbose' mode description */
636 printf(" <-verbose> %sOptional%s\n"
637 " This enables verbose driver/simulator source code"
638 " generation.\n"
639 " Useful for debugging purposes.\n\n", WHITE_CLR, END_CLR);
641 /* '-dir' mode description */
642 printf(" <-d> %sOptional%s\n"
643 " Change root directory, where generated driver source code"
644 " will reside.\n"
645 " Default one is 'genDriverDeposit'\n\n",
646 WHITE_CLR, END_CLR);
648 /* '-general' mode description */
649 printf(" <-general> %sOptional%s\n", WHITE_CLR, END_CLR);
650 printf(" Normal users should ignore this option.\n If all that you"
651 " want - is to generate a Driver/Simulator framework for a\n"
652 " given module, and you didn't make any changes in"
653 " installation procedure\n and library code (that is usially"
654 " the case), than you should ignore\n this option. Only"
655 " general purpose files (i.e. identical for all types of \n"
656 " Driver/Simulator) will be generated. These are module"
657 " Driver/Simulator\n installation and unistallaion programs,"
658 " 'DriverAccess' library and general\n header files. Normally,"
659 " general purpose part should be rebuild by 'driverGen'\n"
660 " software developer, and only in case of it's modification."
661 " Bus type (pci or\n vme) should be provided.\n\n");
663 /* show some examples examples */
664 printf("EXAMPLES: %s BNLDSP vme -gall\n"
665 " %s SHARED_CIBC vme\n\n",
666 progName, progName);
669 #define OPT_COLLIDE(__opt) \
670 ({ \
671 int __val; \
672 if (genOpt & (~__opt)) { \
673 genOpt = OPT_COLLIDE; \
674 __val = 1; \
675 } else \
676 __val = 0; \
677 __val; \
679 #define MAX_NON_OPT_ARGS 3 /* max non-option arguments amount */
682 * @brief Parses command line arguments.
684 * @param argc -- command line argument count
685 * @param argv -- command line argument array
686 * @param md -- module description
688 * @return void
690 static void ParseProgArgs(int argc, char *argv[], struct mdescr *md)
692 int cur_opt; /* currently parsed option */
693 char arg_mas[MAX_NON_OPT_ARGS][NAME_LEN]; /* hold all non-option
694 arguments */
695 int arg_cntr = 0; /* non-option arguments counter */
696 int expected_arg_amount = 0;
698 memset(arg_mas, 0, sizeof(arg_mas));
699 while (((cur_opt =
700 getopt_long_only(argc, argv, "-hv", allLongOptions,
701 NULL)) != EOF) && (genOpt != OPT_COLLIDE)
702 && (glob_srv_arg != SRV_ARG_ERROR) && (arg_cntr != 27051977)) {
703 switch (cur_opt) {
704 case 1: /* this is non-option arg */
705 if (arg_cntr == MAX_NON_OPT_ARGS) {
706 arg_cntr = 27051977;
707 break;
709 strncpy(arg_mas[arg_cntr], optarg, NAME_LEN);
710 arg_mas[arg_cntr][NAME_LEN - 1] = 0; /* safety
711 terminate */
712 ++arg_cntr;
713 break;
714 case 'h': /* user need help */
715 DisplayUsage(argv[0]);
716 exit(EXIT_SUCCESS); /* 0 */
717 break;
718 case 'g': /* generate driver, controlled by git */
719 if (OPT_COLLIDE(OPT_G_IT))
720 break;
721 genOpt = OPT_G_IT;
722 expected_arg_amount = 2;
723 md->isgit = 1;
724 break;
725 case 'a': /* generate full driver (include user part) */
726 if (OPT_COLLIDE(OPT_G_ALL))
727 break;
728 genOpt = OPT_G_ALL;
729 expected_arg_amount = 2;
730 break;
731 case 'i': /* only info file */
732 if (OPT_COLLIDE(OPT_G_INFO))
733 break;
734 genOpt = OPT_G_INFO;
735 expected_arg_amount = 2;
736 break;
737 case 'e': /* general part only (-general) */
738 if (OPT_COLLIDE(OPT_G_SHARED))
739 break;
740 genOpt = OPT_G_SHARED;
741 expected_arg_amount = 0;
742 busType = strdup(optarg); /* set bus type */
743 driverName = strdup("GENERAL"); /* set name for
744 general part */
745 break;
746 case 's': /* we have service option */
747 /* see serviceOptions.h for more info */
748 if (OPT_COLLIDE(OPT_G_SERVICE))
749 break;
750 genOpt = OPT_G_SERVICE;
751 /* they've got non-option arguments. set their amount */
752 if (!strcmp(optarg, "drvrvers")) {
753 expected_arg_amount = 3;
754 glob_srv_arg = SRV_VF_DRVR; /* Verion File for
755 the driver */
756 } else if (!strcmp(optarg, "simvers")) {
757 expected_arg_amount = 3;
758 glob_srv_arg = SRV_VF_SIM; /* Version File for
759 the simulator */
760 } else {
761 expected_arg_amount = 0;
762 glob_srv_arg = SRV_ARG_ERROR;
764 break;
765 case 'n': /* verbose printout during code generation */
766 verboseMode = TRUE;
767 break;
768 case 'd': /* root directory, where driver directory will be created */
769 asprintf(&md->mdn, "%s", optarg);
770 break;
771 case 'v': /* version string */
772 printf("%s [Compiled on %s %s]\n", dg_version,
773 __DATE__, __TIME__);
774 exit(EXIT_SUCCESS);
775 break;
776 case '?': /* wrong option */
777 default:
778 fprintf(stderr, "Wrong option.\n");
779 fprintf(stderr, "Try \'%s -h\' for more information.\n",
780 argv[0]);
781 exit(EXIT_FAILURE); /* 1 */
782 break;
786 if (genOpt == OPT_COLLIDE) { /* check for option colliding */
787 fprintf(stderr, "Option collision detected!\n");
788 fprintf(stderr, "Try \'%s -h\' for more information.\n",
789 argv[0]);
790 exit(EXIT_FAILURE); /* 1 */
793 if (!genOpt) { /* user didn't provide command line
794 option -- set default */
795 genOpt = OPT_G_IT; /* by default create git-controlled driver */
796 expected_arg_amount = 2;
799 if (glob_srv_arg == SRV_ARG_ERROR) { /* check service option argument */
800 fprintf(stderr, "Wrong service option argument.\n");
801 fprintf(stderr, "Try \'%s -h\' for more information.\n",
802 argv[0]);
803 exit(EXIT_FAILURE); /* 1 */
806 if (arg_cntr != expected_arg_amount) { /* check for argument amount */
807 fprintf(stderr, "Wrong arguments.\n");
808 fprintf(stderr, "Try \'%s -h\' for more information.\n",
809 argv[0]);
810 exit(EXIT_FAILURE); /* 1 */
813 /* now we handle all non-option arguments
814 (they are in 'arg_mas' massive) */
815 switch (genOpt) {
816 case OPT_G_IT:
817 case OPT_G_ALL:
818 case OPT_G_INFO:
819 driverName = strdup(arg_mas[0]); /* set DB driver name */
820 busType = strdup(arg_mas[1]); /* set bus type */
821 break;
822 case OPT_G_SHARED:
823 break; /* nothing to do */
824 case OPT_G_SERVICE:
825 switch (glob_srv_arg) {
826 case SRV_VF_DRVR:
827 case SRV_VF_SIM:
828 driverName = strdup(arg_mas[0]); /* set DB driver
829 name */
830 busType = strdup(arg_mas[1]); /* set bus type */
831 SetSrvOptArgs(glob_srv_arg, arg_mas[2]);
832 break;
833 default:
834 break;
836 default:
837 break;
840 if (!CheckBusType(busType)) { /* check 'Bus Type' */
841 fprintf(stderr, "Try \'%s -h\' for more information.\n",
842 argv[0]);
843 exit(EXIT_FAILURE); /* 1 */
846 if (!md->mdn)
847 asprintf(&md->mdn, "%s", DEFAULT_MASTER_DIR);
851 * @brief Free allocated resources of module description.
853 * @param md -- module description.
856 static void free_md(struct mdescr *md)
858 if (md->mdn)
859 free(md->mdn);