/** Generate all output in LLnextgen style This function opens the output files, and writes all necessary output to them. */ void generateLLgenStyle(void) { int i; openOutputs(); /* First generate all the default declarations and defines. */ generateHeaderFile(hOutput); generateDefaultGlobalDeclarations(cOutput, NULL); /* We do this here, because for LLnextgen style output we don't want this in generateDefaultGlobalDeclarations. */ if (!option.noLLreissue) tfputs(cOutput, "#define LL_NEW_TOKEN (-2)\n"); generateDirectiveCodeAtEnd(cOutput); /* These are necessary PER .c file */ for (i = 0; i < listSize(outputs); i++) { FileListItem *lOutput = (FileListItem *) listIndex(outputs, i); generateDefaultLocalDeclarations(lOutput->output, hOutput->name); generateDirectiveDeclarations(lOutput->output); } /* Now where ready to generate the code. */ generateCode(); closeFile(hOutput, true); closeFile(cOutput, true); for (i = 0; i < listSize(outputs); i++) { FileListItem *lOutput = (FileListItem *) listIndex(outputs, i); closeFile(lOutput->output, true); free(lOutput); } deleteList(outputs); }
void lindexCommand(redisClient *c) { robj *o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk); if (o == NULL || checkType(c,o,REDIS_LIST)) return; int index = atoi(c->argv[2]->ptr); robj *value = NULL; if (o->encoding == REDIS_ENCODING_ZIPLIST) { unsigned char *p; unsigned char *vstr; unsigned int vlen; long long vlong; p = ziplistIndex(o->ptr,index); if (ziplistGet(p,&vstr,&vlen,&vlong)) { if (vstr) { value = createStringObject((char*)vstr,vlen); } else { value = createStringObjectFromLongLong(vlong); } addReplyBulk(c,value); decrRefCount(value); } else { addReply(c,shared.nullbulk); } } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) { listNode *ln = listIndex(o->ptr,index); if (ln != NULL) { value = listNodeValue(ln); addReplyBulk(c,value); } else { addReply(c,shared.nullbulk); } } else { redisPanic("Unknown list encoding"); } }
/** Write code for code fragements and @a NonTerminal's to file Note: for LLgen style code generation, each @a NonTerminal is written to the output file corresponding to the input file in which it was declared. */ static void generateCode(void) { int i; Declaration *declaration; FileListItem *output; for (i = 0; i < listSize(declarations); i++) { declaration = (Declaration *) listIndex(declarations, i); switch (declaration->subtype) { case CODE: output = findOutput(declaration->uCode->fileName); outputCode(output->output, declaration->uCode, false); break; case DIRECTIVE: /* output = findOutput(declaration->uDirective->token[0]->fileName); */ break; case NONTERMINAL: output = findOutput(declaration->uNonTerminal->token->fileName); /* Generate the declarations for all generated NonTerminal functions right before the first one (for each file), so we always declare them before use. */ if (output->firstNonTerminal) { output->firstNonTerminal = false; generatePrototypes(output->output); } generateNonTerminalCode(output->output, declaration->uNonTerminal); break; default: PANIC(); } } }
/** Print the alternatives of a @a Term @param term The @a Term to print */ static void printTerm(Term *term) { int i; Alternative *alternative; for (i = 0; i < listSize(term->rule); i++) { alternative = (Alternative *) listIndex(term->rule, i); if (listSize(term->rule) != 1) printSet("Alternative on", alternative->first); if (alternative->flags & ALTERNATIVE_PREFER) { printIndent(); fputs("%prefer\n", printRuleOutput); } if (alternative->flags & ALTERNATIVE_AVOID) { printIndent(); fputs("%avoid\n", printRuleOutput); } if (alternative->flags & ALTERNATIVE_IF) { printIndent(); fprintf(printRuleOutput, "%%if %s\n", alternative->expression->text); } if (alternative->flags & ALTERNATIVE_DEFAULT && listSize(term->rule) != 1) { printIndent(); fputs("%default\n", printRuleOutput); } printAlternative(alternative); if (i < listSize(term->rule) - 1) { indent--; printIndent(); fputs("|\n", printRuleOutput); indent++; } } }
void lrangeCommand(redisClient *c) { robj *o; long start, end, llen, rangelen; if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != REDIS_OK) || (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != REDIS_OK)) return; if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk)) == NULL || checkType(c,o,REDIS_LIST)) return; llen = listTypeLength(o); /* convert negative indexes */ if (start < 0) start = llen+start; if (end < 0) end = llen+end; if (start < 0) start = 0; /* Invariant: start >= 0, so this test will be true when end < 0. * The range is empty when start > end or start >= length. */ if (start > end || start >= llen) { addReply(c,shared.emptymultibulk); return; } if (end >= llen) end = llen-1; rangelen = (end-start)+1; /* Return the result in form of a multi-bulk reply */ addReplyMultiBulkLen(c,rangelen); if (o->encoding == REDIS_ENCODING_ZIPLIST) { unsigned char *p = ziplistIndex(o->ptr,start); unsigned char *vstr; unsigned int vlen; long long vlong; while(rangelen--) { ziplistGet(p,&vstr,&vlen,&vlong); if (vstr) { addReplyBulkCBuffer(c,vstr,vlen); } else { addReplyBulkLongLong(c,vlong); } p = ziplistNext(o->ptr,p); } } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) { listNode *ln; /* If we are nearest to the end of the list, reach the element * starting from tail and going backward, as it is faster. */ if (start > llen/2) start -= llen; ln = listIndex(o->ptr,start); while(rangelen--) { addReplyBulk(c,ln->value); ln = ln->next; } } else { redisPanic("List encoding is not LINKEDLIST nor ZIPLIST!"); } }
/* Initialize an iterator at the specified index. */ listTypeIterator *listTypeInitIterator(robj *subject, long index, unsigned char direction) { listTypeIterator *li = zmalloc(sizeof(listTypeIterator)); li->subject = subject; li->encoding = subject->encoding; li->direction = direction; if (li->encoding == REDIS_ENCODING_ZIPLIST) { li->zi = ziplistIndex(subject->ptr,index); } else if (li->encoding == REDIS_ENCODING_LINKEDLIST) { li->ln = listIndex(subject->ptr,index); } else { redisPanic("Unknown list encoding"); } return li; }
/** Find the output file for the specified input file @param filename The name of the input file */ static FileListItem *findOutput(const char *inputName) { static FileListItem *lastFound = NULL; int i; if (lastFound != NULL && lastFound->sourceFileName == inputName) return lastFound; for (i = 0; i < listSize(outputs); i++) { lastFound = (FileListItem *) listIndex(outputs, i); if (lastFound->sourceFileName == inputName) return lastFound; } PANIC(); }
/** Determine whether a Term contains a conflict @a term The Term to check. */ static bool termContainsConflict(Term *term) { int i; Alternative *alternative; if (term->flags & TERM_RCONFLICT) return true; for (i = 0; i < listSize(term->rule); i++) { alternative = (Alternative *) listIndex(term->rule, i); if (alternativeContainsConflict(alternative)) return true; } return false; }
/** Determine whether an Alternative contains a conflict @a alternative The Alternative to check. */ static bool alternativeContainsConflict(Alternative *alternative) { int i; GrammarPart *grammarPart; if (alternative->flags & ALTERNATIVE_ACONFLICT) return true; for (i = 0; i < listSize(alternative->parts); i++) { grammarPart = (GrammarPart *) listIndex(alternative->parts, i); if (grammarPart->subtype == PART_TERM && termContainsConflict(&grammarPart->uTerm)) return true; } return false; }
/** Print the parts of an @a Alternative @param alternative The @a Alternative to print Note: actions are printed only as {...} */ static void printAlternative(Alternative *alternative) { GrammarPart *grammarPart; int i; for (i = 0; i < listSize(alternative->parts); i++) { grammarPart = (GrammarPart *) listIndex(alternative->parts, i); printIndent(); switch (grammarPart->subtype) { case PART_ACTION: fputs("{...}", printRuleOutput); break; case PART_TERMINAL: case PART_LITERAL: fputs(grammarPart->token->text, printRuleOutput); break; case PART_NONTERMINAL: case PART_UNDETERMINED: fputs(grammarPart->token->text, printRuleOutput); break; case PART_TERM: fputs("[\n", printRuleOutput); /* Only print the sets for repeating terms */ if (!(grammarPart->uTerm.repeats.subtype == FIXED && grammarPart->uTerm.repeats.number == 1)) { printSet("First-set", grammarPart->uTerm.first); printSet("Contains-set", grammarPart->uTerm.contains); printSet("Follow-set", grammarPart->uTerm.follow); } indent++; if (grammarPart->uTerm.flags & TERM_WHILE) { printIndent(); fprintf(printRuleOutput, "%%while %s\n", grammarPart->uTerm.expression->text); } if (grammarPart->uTerm.flags & TERM_PERSISTENT) { printIndent(); fputs("%persistent\n", printRuleOutput); } printTerm(&grammarPart->uTerm); indent--; printIndent(); fputc(']', printRuleOutput); printRepeats(grammarPart->uTerm.repeats); break; default: PANIC(); } fputc('\n', printRuleOutput); } }
void lsetCommand(redisClient *c) { int slotnum = keyHashSlot(c->argv[1]->ptr, sdslen(c->argv[1]->ptr)); robj *o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr,slotnum); if (o == NULL || checkType(c,o,REDIS_LIST)) return; long index; robj *value = (c->argv[3] = tryObjectEncoding(c->argv[3])); if ((getLongFromObjectOrReply(c, c->argv[2], &index, NULL) != REDIS_OK)) return; listTypeTryConversion(o,value); if (o->encoding == REDIS_ENCODING_ZIPLIST) { unsigned char *p, *zl = o->ptr; p = ziplistIndex(zl,index); if (p == NULL) { addReply(c,shared.outofrangeerr); } else { o->ptr = ziplistDelete(o->ptr,&p); value = getDecodedObject(value); o->ptr = ziplistInsert(o->ptr,p,value->ptr,sdslen(value->ptr)); decrRefCount(value); addReply(c,shared.ok); signalModifiedKey(c->db,c->argv[1],slotnum); notifyKeyspaceEvent(REDIS_NOTIFY_LIST,"lset",c->argv[1],c->db->id); server.dirty++; } } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) { listNode *ln = listIndex(o->ptr,index); if (ln == NULL) { addReply(c,shared.outofrangeerr); } else { decrRefCount((robj*)listNodeValue(ln)); listNodeValue(ln) = value; incrRefCount(value); addReply(c,shared.ok); signalModifiedKey(c->db,c->argv[1],slotnum); notifyKeyspaceEvent(REDIS_NOTIFY_LIST,"lset",c->argv[1],c->db->id); server.dirty++; } } else { redisPanic("Unknown list encoding"); } }
void lsetCommand(redisClient *c) { robj *o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr); if (o == NULL || checkType(c,o,REDIS_LIST)) return; int index = atoi(c->argv[2]->ptr); robj *value = (c->argv[3] = tryObjectEncoding(c->argv[3])); listTypeTryConversion(o,value); if (o->encoding == REDIS_ENCODING_ZIPLIST) { unsigned char *p, *zl = o->ptr; p = ziplistIndex(zl,index); if (p == NULL) { addReply(c,shared.outofrangeerr); } else { o->ptr = ziplistDelete(o->ptr,&p); value = getDecodedObject(value); o->ptr = ziplistInsert(o->ptr,p,value->ptr,sdslen(value->ptr)); decrRefCount(value); addReply(c,shared.ok); signalModifiedKey(c->db,c->argv[1]); server.dirty++; } } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) { listNode *ln = listIndex(o->ptr,index); if (ln == NULL) { addReply(c,shared.outofrangeerr); } else { decrRefCount((robj*)listNodeValue(ln)); listNodeValue(ln) = value; incrRefCount(value); addReply(c,shared.ok); signalModifiedKey(c->db,c->argv[1]); server.dirty++; } } else { redisPanic("Unknown list encoding"); } }
int main(int argc, char *argv[]) { unsigned char *zl, *p; unsigned char *entry; unsigned int elen; long long value; /* If an argument is given, use it as the random seed. */ if (argc == 2) srand(atoi(argv[1])); zl = createIntList(); ziplistRepr(zl); zl = createList(); ziplistRepr(zl); pop(zl,ZIPLIST_TAIL); ziplistRepr(zl); pop(zl,ZIPLIST_HEAD); ziplistRepr(zl); pop(zl,ZIPLIST_TAIL); ziplistRepr(zl); pop(zl,ZIPLIST_TAIL); ziplistRepr(zl); printf("Get element at index 3:\n"); { zl = createList(); p = ziplistIndex(zl, 3); if (!ziplistGet(p, &entry, &elen, &value)) { printf("ERROR: Could not access index 3\n"); return 1; } if (entry) { if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite"); printf("\n"); } else { printf("%lld\n", value); } printf("\n"); } printf("Get element at index 4 (out of range):\n"); { zl = createList(); p = ziplistIndex(zl, 4); if (p == NULL) { printf("No entry\n"); } else { printf("ERROR: Out of range index should return NULL, returned offset: %ld\n", p-zl); return 1; } printf("\n"); } printf("Get element at index -1 (last element):\n"); { zl = createList(); p = ziplistIndex(zl, -1); if (!ziplistGet(p, &entry, &elen, &value)) { printf("ERROR: Could not access index -1\n"); return 1; } if (entry) { if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite"); printf("\n"); } else { printf("%lld\n", value); } printf("\n"); } printf("Get element at index -4 (first element):\n"); { zl = createList(); p = ziplistIndex(zl, -4); if (!ziplistGet(p, &entry, &elen, &value)) { printf("ERROR: Could not access index -4\n"); return 1; } if (entry) { if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite"); printf("\n"); } else { printf("%lld\n", value); } printf("\n"); } printf("Get element at index -5 (reverse out of range):\n"); { zl = createList(); p = ziplistIndex(zl, -5); if (p == NULL) { printf("No entry\n"); } else { printf("ERROR: Out of range index should return NULL, returned offset: %ld\n", p-zl); return 1; } printf("\n"); } printf("Iterate list from 0 to end:\n"); { zl = createList(); p = ziplistIndex(zl, 0); while (ziplistGet(p, &entry, &elen, &value)) { printf("Entry: "); if (entry) { if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite"); } else { printf("%lld", value); } p = ziplistNext(zl,p); printf("\n"); } printf("\n"); } printf("Iterate list from 1 to end:\n"); { zl = createList(); p = ziplistIndex(zl, 1); while (ziplistGet(p, &entry, &elen, &value)) { printf("Entry: "); if (entry) { if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite"); } else { printf("%lld", value); } p = ziplistNext(zl,p); printf("\n"); } printf("\n"); } printf("Iterate list from 2 to end:\n"); { zl = createList(); p = ziplistIndex(zl, 2); while (ziplistGet(p, &entry, &elen, &value)) { printf("Entry: "); if (entry) { if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite"); } else { printf("%lld", value); } p = ziplistNext(zl,p); printf("\n"); } printf("\n"); } printf("Iterate starting out of range:\n"); { zl = createList(); p = ziplistIndex(zl, 4); if (!ziplistGet(p, &entry, &elen, &value)) { printf("No entry\n"); } else { printf("ERROR\n"); } printf("\n"); } printf("Iterate from back to front:\n"); { zl = createList(); p = ziplistIndex(zl, -1); while (ziplistGet(p, &entry, &elen, &value)) { printf("Entry: "); if (entry) { if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite"); } else { printf("%lld", value); } p = ziplistPrev(zl,p); printf("\n"); } printf("\n"); } printf("Iterate from back to front, deleting all items:\n"); { zl = createList(); p = ziplistIndex(zl, -1); while (ziplistGet(p, &entry, &elen, &value)) { printf("Entry: "); if (entry) { if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite"); } else { printf("%lld", value); } zl = ziplistDelete(zl,&p); p = ziplistPrev(zl,p); printf("\n"); } printf("\n"); } printf("Delete inclusive range 0,0:\n"); { zl = createList(); zl = ziplistDeleteRange(zl, 0, 1); ziplistRepr(zl); } printf("Delete inclusive range 0,1:\n"); { zl = createList(); zl = ziplistDeleteRange(zl, 0, 2); ziplistRepr(zl); } printf("Delete inclusive range 1,2:\n"); { zl = createList(); zl = ziplistDeleteRange(zl, 1, 2); ziplistRepr(zl); } printf("Delete with start index out of range:\n"); { zl = createList(); zl = ziplistDeleteRange(zl, 5, 1); ziplistRepr(zl); } printf("Delete with num overflow:\n"); { zl = createList(); zl = ziplistDeleteRange(zl, 1, 5); ziplistRepr(zl); } printf("Delete foo while iterating:\n"); { zl = createList(); p = ziplistIndex(zl,0); while (ziplistGet(p,&entry,&elen,&value)) { if (entry && strncmp("foo",(char*)entry,elen) == 0) { printf("Delete foo\n"); zl = ziplistDelete(zl,&p); } else { printf("Entry: "); if (entry) { if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite"); } else { printf("%lld",value); } p = ziplistNext(zl,p); printf("\n"); } } printf("\n"); ziplistRepr(zl); } printf("Regression test for >255 byte strings:\n"); { char v1[257],v2[257]; memset(v1,'x',256); memset(v2,'y',256); zl = ziplistNew(); zl = ziplistPush(zl,(unsigned char*)v1,strlen(v1),ZIPLIST_TAIL); zl = ziplistPush(zl,(unsigned char*)v2,strlen(v2),ZIPLIST_TAIL); /* Pop values again and compare their value. */ p = ziplistIndex(zl,0); assert(ziplistGet(p,&entry,&elen,&value)); assert(strncmp(v1,(char*)entry,elen) == 0); p = ziplistIndex(zl,1); assert(ziplistGet(p,&entry,&elen,&value)); assert(strncmp(v2,(char*)entry,elen) == 0); printf("SUCCESS\n\n"); } printf("Regression test deleting next to last entries:\n"); { char v[3][257]; zlentry e[3]; int i; for (i = 0; i < (sizeof(v)/sizeof(v[0])); i++) { memset(v[i], 'a' + i, sizeof(v[0])); } v[0][256] = '\0'; v[1][ 1] = '\0'; v[2][256] = '\0'; zl = ziplistNew(); for (i = 0; i < (sizeof(v)/sizeof(v[0])); i++) { zl = ziplistPush(zl, (unsigned char *) v[i], strlen(v[i]), ZIPLIST_TAIL); } verify(zl, e); assert(e[0].prevrawlensize == 1); assert(e[1].prevrawlensize == 5); assert(e[2].prevrawlensize == 1); /* Deleting entry 1 will increase `prevrawlensize` for entry 2 */ unsigned char *p = e[1].p; zl = ziplistDelete(zl, &p); verify(zl, e); assert(e[0].prevrawlensize == 1); assert(e[1].prevrawlensize == 5); printf("SUCCESS\n\n"); } printf("Create long list and check indices:\n"); { zl = ziplistNew(); char buf[32]; int i,len; for (i = 0; i < 1000; i++) { len = sprintf(buf,"%d",i); zl = ziplistPush(zl,(unsigned char*)buf,len,ZIPLIST_TAIL); } for (i = 0; i < 1000; i++) { p = ziplistIndex(zl,i); assert(ziplistGet(p,NULL,NULL,&value)); assert(i == value); p = ziplistIndex(zl,-i-1); assert(ziplistGet(p,NULL,NULL,&value)); assert(999-i == value); } printf("SUCCESS\n\n"); } printf("Compare strings with ziplist entries:\n"); { zl = createList(); p = ziplistIndex(zl,0); if (!ziplistCompare(p,(unsigned char*)"hello",5)) { printf("ERROR: not \"hello\"\n"); return 1; } if (ziplistCompare(p,(unsigned char*)"hella",5)) { printf("ERROR: \"hella\"\n"); return 1; } p = ziplistIndex(zl,3); if (!ziplistCompare(p,(unsigned char*)"1024",4)) { printf("ERROR: not \"1024\"\n"); return 1; } if (ziplistCompare(p,(unsigned char*)"1025",4)) { printf("ERROR: \"1025\"\n"); return 1; } printf("SUCCESS\n\n"); } printf("Stress with random payloads of different encoding:\n"); { int i,j,len,where; unsigned char *p; char buf[1024]; int buflen; list *ref; listNode *refnode; /* Hold temp vars from ziplist */ unsigned char *sstr; unsigned int slen; long long sval; for (i = 0; i < 20000; i++) { zl = ziplistNew(); ref = listCreate(); listSetFreeMethod(ref, sdsfree); len = rand() % 256; /* Create lists */ for (j = 0; j < len; j++) { where = (rand() & 1) ? ZIPLIST_HEAD : ZIPLIST_TAIL; if (rand() % 2) { buflen = randstring(buf,1,sizeof(buf)-1); } else { switch(rand() % 3) { case 0: buflen = sprintf(buf,"%lld",(0LL + rand()) >> 20); break; case 1: buflen = sprintf(buf,"%lld",(0LL + rand())); break; case 2: buflen = sprintf(buf,"%lld",(0LL + rand()) << 20); break; default: assert(NULL); } } /* Add to ziplist */ zl = ziplistPush(zl, (unsigned char*)buf, buflen, where); /* Add to reference list */ if (where == ZIPLIST_HEAD) { listAddNodeHead(ref,sdsnewlen(buf, buflen)); } else if (where == ZIPLIST_TAIL) { listAddNodeTail(ref,sdsnewlen(buf, buflen)); } else { assert(NULL); } } assert(listLength(ref) == ziplistLen(zl)); for (j = 0; j < len; j++) { /* Naive way to get elements, but similar to the stresser * executed from the Tcl test suite. */ p = ziplistIndex(zl,j); refnode = listIndex(ref,j); assert(ziplistGet(p,&sstr,&slen,&sval)); if (sstr == NULL) { buflen = sprintf(buf,"%lld",sval); } else { buflen = slen; memcpy(buf,sstr,buflen); buf[buflen] = '\0'; } assert(memcmp(buf,listNodeValue(refnode),buflen) == 0); } zfree(zl); listRelease(ref); } printf("SUCCESS\n\n"); } printf("Stress with variable ziplist size:\n"); { stress(ZIPLIST_HEAD,100000,16384,256); stress(ZIPLIST_TAIL,100000,16384,256); } return 0; }
/** Open all required output files Note: for LLgen output an output file is created for each input file. Further, two files, <prefix>pars.h and <prefix>pars.c, are created. */ static void openOutputs(void) { const char *cExtension = "c", *hExtension = "h"; FileListItem *currentItem; const char *inputName, *prefixText; char *outputName; size_t lenPrefix; int i; if (option.extensions) { char *extension = listIndex(option.extensions, 0); if (extension != NULL) cExtension = extension; if (listSize(option.extensions) > 1 && (extension = listIndex(option.extensions, 1)) != NULL) hExtension = extension; } outputs = newList(); if (listSize(option.inputFileList) == 0) { ASSERT(option.outputBaseName != NULL); currentItem = (FileListItem *) safeMalloc(sizeof(FileListItem), "openOutputs"); /* Note that for LLgen style outputs the use of include files is prohibited, so fileName still points to the string "<stdin>". */ currentItem->sourceFileName = fileName; currentItem->firstNonTerminal = true; outputName = createNameWithExtension(option.outputBaseName, cExtension); currentItem->output = checkAndOpenFile(outputName, true); listAppend(outputs, currentItem); } else { /* Open the different output files */ for (i = 0; i < listSize(option.inputFileList); i++) { inputName = (const char *) listIndex(option.inputFileList, i); currentItem = (FileListItem *) safeMalloc(sizeof(FileListItem), "openOutputs"); currentItem->sourceFileName = inputName; /* Set the flag that indicates that we haven't yet generated a NonTerminal */ currentItem->firstNonTerminal = true; /* For LLgen style outputs we never keep the directory, as multiple directories may be present for different files. */ inputName = baseName(inputName); outputName = createNameWithExtension(inputName, cExtension); for (i = 0; i < listSize(outputs); i++) { FileListItem *itemToCheck = (FileListItem *) listIndex(outputs, i); if (strcmp(outputName, itemToCheck->output->name) == 0) fatal("Input files %s and %s map to the same output name.\n", itemToCheck->output->name, outputName); } currentItem->output = checkAndOpenFile(outputName, true); listAppend(outputs, currentItem); } } /* Open Lpars.h and Lpars.c, or appropriatly prefixed version of them */ if (prefixDirective == NULL) { prefixText = "L"; lenPrefix = 1; } else { prefixText = prefixDirective->token[0]->text; lenPrefix = strlen(prefixText); } outputName = (char *) safeMalloc(strlen(prefixText) + 6 + strlen(hExtension), "openOutputs"); sprintf(outputName, "%spars.%s", prefixText, hExtension); hOutput = checkAndOpenFile(outputName, false); outputName = (char *) safeMalloc(strlen(prefixText) + 6 + strlen(cExtension), "openOutputs"); sprintf(outputName, "%spars.%s", prefixText, cExtension); cOutput = checkAndOpenFile(outputName, true); }