static int enter_new_cat_entry(cdc_entry *entry_to_update) { cdc_entry new_entry; char tmp_str[TMP_STRING_LEN + 1]; memset(&new_entry, '\0', sizeof(new_entry)); printf("Enter catalog entry: "); (void)fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); strncpy(new_entry.catalog, tmp_str, CAT_CAT_LEN - 1); printf("Enter title: "); (void)fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); strncpy(new_entry.title, tmp_str, CAT_TITLE_LEN - 1); printf("Enter type: "); (void)fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); strncpy(new_entry.type, tmp_str, CAT_TYPE_LEN - 1); printf("Enter artist: "); (void)fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); strncpy(new_entry.artist, tmp_str, CAT_ARTIST_LEN - 1); printf("\nNew catalog entry entry is :-\n"); display_cdc(&new_entry); if (get_confirm("Add this entry ?")) { memcpy(entry_to_update, &new_entry, sizeof(new_entry)); return(1); } return(0); }
obj eval_function(ref lt, rel rt) {//lt ÇÉXÉ^ÉbÉNêœÇ›Ç… if(type(lt)== tInternalFn) goto ci; if(type(lt)!=tClosure) {print((obj)lt); assert(0);} { list ll = seek_lamb(ul(lt), rt); if(ll && type(first(ll))==tInternalFn) { lt = first(ll); goto ci; } if(! ll) error("no appropriate function."); push(env); obj vars = Assoc(); env = op(vars, retain(third(ll))); bind_vars(&vars, first(ll), rt); release(rt); obj rr = exec(second(ll)); release(env); env = pop(&is); return strip_return(rr); } ci: try { obj rr=(ufn(lt))(rt); release(rt); return rr; } catch(eval_error){ error("not defined for that value."); return nil; } }
static void enter_new_track_entries(const cdc_entry *entry_to_add_to) { cdt_entry new_track, existing_track; char tmp_str[TMP_STRING_LEN + 1]; int track_no = 1; if (entry_to_add_to->catalog[0] == '\0') { return; } printf("\nUpdating tracks for %s\n", entry_to_add_to->catalog); printf("Press return to leave existing description unchanged,\n"); printf(" a single d to delete this and remaining tracks,\n"); printf(" or new track description\n"); while (1) { memset(&new_track, '\0', sizeof(new_track)); existing_track = get_cdt_entry(entry_to_add_to->catalog, track_no); if (existing_track.catalog[0]) { printf("\tTrack %d: %s\n", track_no, existing_track.track_txt); printf("\tNew text: "); } else { printf("\tTrack %d description: ", track_no); } fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); if (strlen(tmp_str) == 0) { if (existing_track.catalog[0] == '\0') { /* no existing entry, so finish adding */ break; } else { /* leave existing entry, jump to next track */ track_no++; continue; } } if ((strlen(tmp_str) == 1) && tmp_str[0] == 'd') { /* delete this and ramaining tracks */ while (del_cdt_entry(entry_to_add_to->catalog, track_no)) { track_no++; } break; } strncpy(new_track.track_txt, tmp_str, TRACK_TTEXT_LEN - 1); strcpy(new_track.catalog, entry_to_add_to->catalog); new_track.track_no = track_no; if (!add_cdt_entry(new_track)) { fprintf(stderr, "Failed to add new track\n"); break; } track_no++; } /* while */ }
obj eval_curry(obj exp, obj vars) { // envÇÕǢNjé¿çsíÜÇà /* push(env); env = op(vars, nil); obj rr = exec(em1(exp)); pop(&env); env = pop(&is); return strip_return(rr); /*/ env = op(vars, env); obj rr = exec(em1(exp)); pop(&env); return strip_return(rr); /**/}
/* Gets a new cdc_entry from the user. If all goes well, saves the * data to the location pointed to by `entry_to_update` * returns 1 if update occurs, 0 if the user aborts */ static int enter_new_cat_entry(cdc_entry *entry_to_update) { cdc_entry new_entry; char tmp_str[TMP_STRING_LEN + 1]; memset(&new_entry, '\0', sizeof(new_entry)); // remember to do this! // the code that follows is kind of copy-pastey, probably should be // factored out. printf("Enter catalog entry: "); fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); strncpy(new_entry.catalog, tmp_str, CAT_LEN - 1); printf("Enter title: "); fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); strncpy(new_entry.title, tmp_str, TITLE_LEN - 1); printf("Enter type: "); fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); strncpy(new_entry.type, tmp_str, TYPE_LEN - 1); printf("Enter artist: "); fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); strncpy(new_entry.artist, tmp_str, ARTIST_LEN - 1); printf("\nNew catalog entry entry is :-\n"); // get a user confirmation before continuint display_cdc(&new_entry); if (get_confirm("Add this entry ?")) { memcpy(entry_to_update, &new_entry, sizeof(new_entry)); return(1); } return(0); }
/* Get information for a new cdc entry. * (just the metadata, not track information) * We use strip_return to get rid of the '\n' that fgets returns. * We avoid using gets, because it is unsafe (no buffer overflow size checks!) * Return 1 on success, 0 if user doesn't confirm. */ static int enter_new_cat_entry(cdc_entry *entry_to_update) { // impl notes: we copy all the data into a new entry first so that we // can display it and ask for confirmation. Only then do we copy into // `entry_to_update`. cdc_entry new_entry; char tmp_str[TMP_STRING_LEN + 1]; memset(&new_entry, '\0', sizeof(new_entry)); printf("Enter catalog entry: "); fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); strncpy(new_entry.catalog, tmp_str, CAT_CAT_LEN - 1); printf("Enter title: "); fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); strncpy(new_entry.title, tmp_str, CAT_TITLE_LEN - 1); printf("Enter type: "); fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); strncpy(new_entry.type, tmp_str, CAT_TYPE_LEN - 1); printf("Enter artist: "); fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); strncpy(new_entry.artist, tmp_str, CAT_ARTIST_LEN - 1); printf("\nNew catalog entry entry is :-\n"); display_cdc(&new_entry); if (get_confirm("Add this entry ?")) { memcpy(entry_to_update, &new_entry, sizeof(new_entry)); return(1); } return(0); }
/* Finds a catalog entry. It handles multiple matches by letting the user pick * one of them. If there are no matches, search_cdc_entry will set item_found * to be all 0 bytes and we will wind up with no active catalog entry. */ static cdc_entry find_cat(void) { cdc_entry item_found; char tmp_str[TMP_STRING_LEN + 1]; int first_call = 1; int any_entry_found = 0; int string_ok; int entry_selected = 0; // get a search string, checking that the string isn't too long do { string_ok = 1; printf("Enter string to search for in catalog entry: "); fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); if (strlen(tmp_str) > CAT_LEN) { fprintf(stderr, "Sorry, string too long, maximum %d characters", CAT_LEN); string_ok = 0; } } while (!string_ok); // loop over all cdc entries. The `first_time` is a flag which should // be 1 ("first time = true") on the initial call; it gets set to 0 (note // it's passed via ptr), and internally the database code tracks the // progress of the search from that point forward while (!entry_selected) { item_found = search_cdc_entry(tmp_str, &first_call); if (item_found.catalog[0] != '\0') { any_entry_found = 1; printf("\n"); display_cdc(&item_found); if (get_confirm("This entry? ")) { entry_selected = 1; } } else { // we can get here either because the user didn't select any // of the matches, or because there weren't any. if (any_entry_found) { printf("Sorry, no more matches found\n"); } else { printf("Sorry, no matches found\n"); } break; } } return item_found; }
obj udef_op0(obj ope, obj v){ assert(type(ope)==tSymbol); obj lamb = find_var(ope); if(!lamb) return nil; assert(type(lamb)==tClosure); list ll = seek_lamb(ul(lamb), v); if(! ll) { return nil; } if(type(first(ll))==tInternalFn) error("user-defined operator not defined for the type."); obj vars = Assoc(); bind_vars(&vars, first(ll), v); push(env); env = op(vars, retain(third(ll))); release(lamb); //execÇÃǻǩÇ≈lambÇ™çÌèúÇ≥ÇÍÇÈâ¬î\ê´Ç†ÇË obj rr = exec(second(ll)); release(env); env = pop(&is); return strip_return(rr); }
/* A simple catalog search facility. We allow the user to * enter a string, then check for catalog entries that contain the string. * Since there could be multiple entries that match, we simply offer the user * each match in turn. */ static cdc_entry find_cat(void) { cdc_entry item_found; char tmp_str[TMP_STRING_LEN + 1]; int first_call = 1; int any_entry_found = 0; int string_ok; int entry_selected = 0; do { string_ok = 1; printf("Enter string to search for in catalog entry: "); fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); if (strlen(tmp_str) > CAT_CAT_LEN) { fprintf(stderr, "Sorry, string too long, maximum %d \ characters\n", CAT_CAT_LEN); string_ok = 0; } } while (!string_ok); while (!entry_selected) { // the first_call flag starts as 1, and is set to 0 inside of the // search_cdc_entry function, which uses module-level variables to // handle the "curser" over results. item_found = search_cdc_entry(tmp_str, &first_call); if (item_found.catalog[0] != '\0') { any_entry_found = 1; printf("\n"); display_cdc(&item_found); if (get_confirm("This entry? ")) { entry_selected = 1; } } else { if (any_entry_found) printf("Sorry, no more matches found\n"); else printf("Sorry, nothing found\n"); break; } } return(item_found); }
static cdc_entry find_cat(void) { cdc_entry item_found; char tmp_str[TMP_STRING_LEN + 1]; int first_call = 1; int any_entry_found = 0; int string_ok; int entry_selected = 0; do { string_ok = 1; printf("Enter string to search for in catalog entry: \n"); fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); if (strlen(tmp_str) > CAT_CAT_LEN) { fprintf(stderr, "Sorry, string too long, maxmium %d \ characters\n", CAT_CAT_LEN); string_ok = 0; } } while (!string_ok); while (!entry_selected) { item_found = search_cdc_entry(tmp_str, &first_call); if (item_found.catalog[0] != '\0') { any_entry_found = 1; printf("\n"); display_cdc(&item_found); if (get_confirm("This entry? ")) { entry_selected = 1; } } else { if (any_entry_found) printf("Sorry, no more matches found\n"); else printf("Sorry, nothing found\n"); break; } } return item_found; }
char *url_decode(char *str) { int cpt[2]; char nb[5]; memset(nb, 0, 5); for (cpt[0] = cpt[1] = 0; str[cpt[0]]; cpt[0]++, cpt[1]++) if (str[cpt[0]] == '%' && str[cpt[0] + 1] && ((str[cpt[0] + 1] >= '0' && str[cpt[0] + 1] <= '9') || (str[cpt[0] + 1] >= 'A' && str[cpt[0] + 1] <= 'F') || (str[cpt[0] + 1] >= 'a' && str[cpt[0] + 1] <= 'f'))) { sprintf(nb, "0x%.2s", str + cpt[0] + 1); str[cpt[1]] = strtol(nb, 0, 16); cpt[0] += 2; } else str[cpt[1]] = str[cpt[0]]; str[cpt[1]] = 0; str = strip_return(str); return (str); }
/* Mildly misnamed function... it loops through existing track entries if * there are any and the user can either edit description or delete this and * all later entries. When it finishes looping over existing entries, the user * can also add new ones. */ static void enter_new_track_entries(const cdc_entry *entry_to_add_to) { cdt_entry new_track, existing_track; char tmp_str[TMP_STRING_LEN + 1]; int track_no = 1; // if there's no current catalog, do nothing if (entry_to_add_to->catalog[0] == '\0') return; // print out instructions printf("Updating tracks for %s\n", entry_to_add_to->catalog); printf("Press return to leave existing description unchanged,\n"); printf(" a single d to delete this and remaining tracks,\n"); printf(" or new track description\n"); // loop over tracks, let the user choose what to do with each one. // note that dbm is helping a lot here - in our flat file curses impl // from ch6, the only easy things to do were to keep all tracks or // redo everything. Dbm makes single-track changes much easier. // We are still somewhat limited because the track ids have to be in // increaseing order. So you can edit descriptions atomically, but if // you delete one you have to delete everything later. We could get // around this, but it would be too much work for a demo program. while (1) { memset(&new_track, '\0', sizeof(new_track)); existing_track = get_cdt_entry(entry_to_add_to->catalog, track_no); // existing track.caltalog[0] is set to 0 by get_cdt_entry if there // is no track with track number `track_no`. Hence.. if(existing_track.catalog[0]) { // if we are here, there's a track description already printf("\tTrack %d: %s\n", track_no, existing_track.track_txt); printf("\tNew text: "); } else { // if we are here, there is not printf("\tTrack %d description: ", track_no); } fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); // If tmp_str has length 0, the user didn't want to do anything for // this track. if (strlen(tmp_str) == 0) { if (existing_track.catalog[0] == '\0') { // if this is true, then we had already seen all existing // tracks, so we are done. break; } else { // if we get here, it means the user didn't want to edit this // track, so we go on to the next one. track_no++; continue; } } // Entering a single 'd' is a special case for delete this track and // all later tracks, as mentioned in the instructions printed above. // So, loop through all remaining tracks, delete, then break. if ((strlen(tmp_str) == 1) && tmp_str[0] == 'd') { // del_cdt_entry will return 0 when we try to delete a nonexistant // track_no, so we use that as our terminate condition. while (del_cdt_entry(entry_to_add_to->catalog, track_no)) { track_no++; } break; } // if we get here, it means the user made a new description, so we // edit the existing track or add a new one (the api is the same, so // we don't care at this point whether the track exists) strncpy(new_track.track_txt, tmp_str, TTEXT_LEN - 1); strcpy(new_track.catalog, entry_to_add_to->catalog); new_track.track_no = track_no; if (!add_cdt_entry(new_track)) { fprintf(stderr, "Failed to add new track\n"); break; } track_no++; } // end of the big while loop over track_no's }
static void enter_new_track_entries(const cdc_entry *entry_to_add_to) { cdt_entry new_track, existing_track; char tmp_str[TMP_STRING_LEN + 1]; int track_no = 1; if (entry_to_add_to->catalog[0] == '\0') return; printf("\nUpdating tracks for %s\n", entry_to_add_to->catalog); printf("Press return to leave existing description unchanged,\n"); printf(" a single d to delete this and remaining tracks,\n"); printf(" or new track description\n"); while(1) { /* First, we must check whether a track already exists with the current track number. Depending on what we find, we change the prompt. */ memset(&new_track, '\0', sizeof(new_track)); existing_track = get_cdt_entry(entry_to_add_to->catalog, track_no); if (existing_track.catalog[0]) { printf("\tTrack %d: %s\n", track_no, existing_track.track_txt); printf("\tNew text: "); } else { printf("\tTrack %d description: ", track_no); } fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); /* If there was no existing entry for this track and the user hasn't added one, we assume that there are no more tracks to be added. */ if (strlen(tmp_str) == 0) { if (existing_track.catalog[0] == '\0') { /* no existing entry, so finished adding */ break; } else { /* leave existing entry, jump to next track */ track_no++; continue; } } /* If the user enters a single d character, this deletes the current and any higher numbered tracks. The del_cdt_entry function will return false if it couldn't find a track to delete. */ if ((strlen(tmp_str) == 1) && tmp_str[0] == 'd') { /* delete this and remaining tracks */ while (del_cdt_entry(entry_to_add_to->catalog, track_no)) { track_no++; } break; } /* Here we get to the code for adding a new track, or updating an existing one. We construct the cdt_entry structure new_track, then call the database function add_cdt_entry to add it to the database. */ strncpy(new_track.track_txt, tmp_str, TRACK_TTEXT_LEN - 1); strcpy(new_track.catalog, entry_to_add_to->catalog); new_track.track_no = track_no; if (!add_cdt_entry(new_track)) { fprintf(stderr, "Failed to add new track\n"); break; } track_no++; } /* while */ }
/* Enter new track entries for a cdc entry. * * You have the option of looping through some exiting tracks and leaving * them unchanged, but if you do change anything, it and everything after it * will get deleted. Then you can add lots of tracks if you want. * * You enter a blank line to indicate you are finished. */ static void enter_new_track_entries(const cdc_entry *entry_to_add_to) { cdt_entry new_track, existing_track; char tmp_str[TMP_STRING_LEN + 1]; int track_no = 1; if (entry_to_add_to->catalog[0] == '\0') return; printf("\nUpdating tracks for %s\n", entry_to_add_to->catalog); printf("Press return to leave existing description unchanged,\n"); printf(" a single d to delete this and remaining tracks,\n"); printf(" or new track description\n"); while(1) { // set up a prompt. Either the track exists and we give the user // an option of changing the text, or if the track doesn't exist then // we ask for a description. memset(&new_track, '\0', sizeof(new_track)); existing_track = get_cdt_entry(entry_to_add_to->catalog, track_no); if (existing_track.catalog[0]) { printf("\tTrack %d: %s\n", track_no, existing_track.track_txt); printf("\tNew text: "); } else { printf("\tTrack %d description: ", track_no); } fgets(tmp_str, TMP_STRING_LEN, stdin); strip_return(tmp_str); // if they entered a blank line *and* we already went through existing // tracks, then we are done. // If we aren't finished with existing tracks and they entered a blank // line, just go on to the next one. if (strlen(tmp_str) == 0) { if (existing_track.catalog[0] == '\0') { /* no existing entry, so finished adding */ break; } else { /* leave existing entry, jump to next track */ track_no++; continue; } } // if they entered a d, delete this track and loop through all higher- // numbered tracks and delete them, then exit. if ((strlen(tmp_str) == 1) && tmp_str[0] == 'd') { while (del_cdt_entry(entry_to_add_to->catalog, track_no)) { track_no++; } break; } // otherwise, they entered new track data. Whether or not the track // previously existed, we copy that data into a ctd entry and add it // to the db on the current track_no strncpy(new_track.track_txt, tmp_str, TRACK_TTEXT_LEN - 1); strcpy(new_track.catalog, entry_to_add_to->catalog); new_track.track_no = track_no; if (!add_cdt_entry(new_track)) { fprintf(stderr, "Failed to add new track\n"); break; } track_no++; } }